<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nils</title>
    <description>The latest articles on DEV Community by Nils (@nilscoding).</description>
    <link>https://dev.to/nilscoding</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F464577%2Fb8a328d9-3af6-4983-960d-d0786018f3dd.png</url>
      <title>DEV Community: Nils</title>
      <link>https://dev.to/nilscoding</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nilscoding"/>
    <language>en</language>
    <item>
      <title>Beyond Stream.distinct()</title>
      <dc:creator>Nils</dc:creator>
      <pubDate>Thu, 21 Nov 2024 23:28:55 +0000</pubDate>
      <link>https://dev.to/nilscoding/beyond-streamdistinct-5a05</link>
      <guid>https://dev.to/nilscoding/beyond-streamdistinct-5a05</guid>
      <description>&lt;h2&gt;
  
  
  A Stream of objects
&lt;/h2&gt;

&lt;p&gt;Starting with Java 8, you can use a &lt;code&gt;Stream&lt;/code&gt; to process elements from a &lt;code&gt;Collection&lt;/code&gt; (mostly classes derived from &lt;code&gt;List&lt;/code&gt; or &lt;code&gt;Set&lt;/code&gt; will be used for this) in an iterating way, defining filtering and mapping lazily, and then "consume" the Stream.&lt;/p&gt;

&lt;p&gt;You can transform the elements in a Stream for further processing by extracting values from objects (e.g. getting the city name from a person or calculating the length of a string) and filter elements (e.g. only persons older than x years or cities starting with "D") before consuming the resulting Stream of elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What defines "distinct"?
&lt;/h2&gt;

&lt;p&gt;One special way of filtering elements in a Stream is using &lt;code&gt;distinct()&lt;/code&gt; to return unique elements. Checking for uniqueness is internally done via the &lt;code&gt;equals()&lt;/code&gt; method of the processed elements, so you need to implement both &lt;code&gt;equals()&lt;/code&gt; and &lt;code&gt;hashCode()&lt;/code&gt; accordingly to be able to use &lt;code&gt;distinct()&lt;/code&gt;. While simple classes like &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Long&lt;/code&gt; or &lt;code&gt;LocalDate&lt;/code&gt; work like expected, it might be difficult to correctly implement those methods for custom objects. And of course, this puts a limit on how custom objects can be processed, because you can only implement one way of checking for "equal" elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  A more flexible, yet easy solution
&lt;/h2&gt;

&lt;p&gt;First, you need to define a function that extracts the unique field from your custom object.&lt;/p&gt;

&lt;p&gt;For example, we take this object representing a very simple person entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Person {
    private int id;
    private String firstname;
    private String lastname;

    public Person() { }

    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return this.id;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getFirstname() {
        return this.firstname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
    public String getLastname() {
        return this.lastname;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get the ID by calling &lt;code&gt;p.getId()&lt;/code&gt; on a Person object &lt;code&gt;p&lt;/code&gt;. Or, to describe this as a function reference: &lt;code&gt;Person::getId&lt;/code&gt;.&lt;br&gt;
The same goes for &lt;code&gt;Person::getFirstname&lt;/code&gt; and &lt;code&gt;Person::getLastname&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our list &lt;code&gt;l&lt;/code&gt; (e.g. an &lt;code&gt;ArrayList&amp;lt;Person&amp;gt;&lt;/code&gt;) contains some person entries and we want to get unique entries from that list, based on the &lt;code&gt;lastname&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;For this we can use &lt;code&gt;Collectors.groupingBy(...)&lt;/code&gt; with referencing the access function of a property and another Collector that "remembers" the first non-null person element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map&amp;lt;String, Person&amp;gt; m = l.stream()
    .collect(Collectors.groupingBy(
        Person::getLastname,
        Collectors.reducing(null, (a, b) -&amp;gt; (a != null) ? a : b))
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In result, we will get a map with all distinct last names as keys and the first person element with that last name as corresponding value.&lt;br&gt;
If needed, the reduction collector can be changed to return the last person instead: &lt;code&gt;Collectors.reducing(null, (a, b) -&amp;gt; (b != null) ? b : a))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Optionally, you can insert &lt;code&gt;LinkedHashMap::new&lt;/code&gt; between the the access function and the reduction collector. This specifies the type of map that will be used to return the grouped data. When using a &lt;code&gt;LinkedHashMap&lt;/code&gt; the processing order of the elements will be retained in the result. However, this is actually limited by the specifications of the given stream, so the results may vary.&lt;/p&gt;

&lt;p&gt;This also works for simple element types, so you can use this logic for both custom and simple objects. For simple objects the access function is just &lt;code&gt;(obj) -&amp;gt; obj&lt;/code&gt; or &lt;code&gt;Function.identity()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downsides and alternatives
&lt;/h2&gt;

&lt;p&gt;The main downside of this method is that &lt;code&gt;Stream.collect(...)&lt;/code&gt; is a &lt;em&gt;terminal operation&lt;/em&gt;. This means that calling &lt;code&gt;collect(...)&lt;/code&gt; will consume the stream and process all the filterings and mappings that are defined on the Stream. It will then return a final result of the collect operation, in our case the result map.&lt;br&gt;
Of course, you can get a new Stream on the values or key set of that map for further processing, but the source Stream has been consumed at that point.&lt;br&gt;
In contrast, &lt;code&gt;distinct()&lt;/code&gt; is a &lt;em&gt;stateful intermediate operation&lt;/em&gt; which returns a new Stream, but no operation is done at that moment on the source Stream.&lt;/p&gt;

&lt;p&gt;Some open source projects like Eclipse Collections and Vavr provide alternatives to lists, sets, maps and streams which also include the option to define an access function to an object property when collecting distinct elements.&lt;/p&gt;

&lt;p&gt;And there are some other clever alternatives described in the answers of this &lt;a href="https://stackoverflow.com/q/23699371/694804" rel="noopener noreferrer"&gt;StackOverflow question&lt;/a&gt;. Btw. my personal favorite there is returning a Predicate via a helper method &lt;code&gt;distinctByKey(...)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The standard method &lt;code&gt;Stream.distinct()&lt;/code&gt; works well for simple types and custom objects that provide a fixed way to determine object equality.&lt;br&gt;
If you need more flexibility on defining which property (or even a combination of multiple properties) make an object unique and filter data accordingly, you can utilize provided Collector implementations, build custom Predicates or Collectors or use other open source collection frameworks.&lt;/p&gt;

</description>
      <category>java</category>
      <category>stream</category>
    </item>
    <item>
      <title>A custom Maven Mojo to show the effective project properties</title>
      <dc:creator>Nils</dc:creator>
      <pubDate>Thu, 28 Dec 2023 00:50:24 +0000</pubDate>
      <link>https://dev.to/nilscoding/a-custom-maven-mojo-to-show-the-effective-project-properties-5ce4</link>
      <guid>https://dev.to/nilscoding/a-custom-maven-mojo-to-show-the-effective-project-properties-5ce4</guid>
      <description>&lt;h2&gt;
  
  
  A custom Maven Mojo?!
&lt;/h2&gt;

&lt;p&gt;Recently I came across the requirement to print all effective project properties during a Maven build. So, why not write a custom Mojo to do that?&lt;/p&gt;

&lt;p&gt;I try to get more into writing custom Maven Mojos, so I created a new project and put together a simple class that accesses the current project and prints all project properties to the Maven build log in info level.&lt;/p&gt;

&lt;p&gt;If you are interested in the code, you can head over to my GitHub and check it out: &lt;a href="https://github.com/NilsCoding/mvn-show-settings"&gt;https://github.com/NilsCoding/mvn-show-settings&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've learned in this project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Injecting the Maven project
&lt;/h3&gt;

&lt;p&gt;You can annotate a field of type &lt;code&gt;org.apache.maven.project.MavenProject&lt;/code&gt; with the &lt;code&gt;@Parameter&lt;/code&gt; annotation and specify &lt;code&gt;defaultValue = "${project}"&lt;/code&gt; as an annotation attribute to inject the current project as an object into the Mojo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency for &lt;code&gt;MavenProject&lt;/code&gt; inject
&lt;/h3&gt;

&lt;p&gt;Also, you need to add &lt;code&gt;org.apache.maven:maven-core&lt;/code&gt; as a dependency to have access to &lt;code&gt;MavenProject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I've included more Maven dependencies in my &lt;code&gt;mvn-show-settings&lt;/code&gt; project (and commented out some injects in the Mojo code) to have a starting point for extending the Mojo by using more information at build time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom configuration for helper class generation
&lt;/h3&gt;

&lt;p&gt;A custom Maven Mojo project needs some configuration files and a helper class, so it is highly recommeded to include &lt;code&gt;org.apache.maven.plugins:maven-plugin-plugin&lt;/code&gt; in the build process to auto-generate those files. As a side-note, you might want to configure &lt;code&gt;helpPackageName&lt;/code&gt; for that plugin to specify the package of the generated helper class. Otherwise, a package name will be generated from the artifact name and will result in a (maybe) unwanted package name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Excluding generated code from Checkstyle
&lt;/h3&gt;

&lt;p&gt;I've also added a custom Checkstyle configuration to my project to enforce some coding "standards". By default, all sources will be checked, which also includes the gerenated sources for the helper classes. To prevent those helper classes from being checked, you can specify which directories should be included by the Checkstyle plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;sourceDirectories&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;sourceDirectory&amp;gt;&lt;/span&gt;${project.build.sourceDirectory}&lt;span class="nt"&gt;&amp;lt;/sourceDirectory&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sourceDirectories&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you configure Checkstyle to be used in the reporting, then you might want to add this configuration there, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I'm currently working on some other custom Maven Mojos which I will definitely publish on GitHub, too, and there will also be some interesting details on what you can actually do in custom Maven Mojos.&lt;/p&gt;

&lt;p&gt;So, stay tuned. 😉&lt;/p&gt;

</description>
      <category>maven</category>
      <category>java</category>
    </item>
  </channel>
</rss>
