title: Merge two collections using streams, but only unique values, and using predicate instead of equals?
body: <p>I'm trying to <strong>merge</strong> two collections, but do it <strong>conditionally</strong> where I only want to add <strong>unique</strong> values. And what constitutes <strong>uniqueness</strong> should be decided by a <strong>predicate</strong> (or similar), not the <strong>equals</strong> function.</p>
  
  <p>For example, let's assume we have the following two collections of Person objects:</p>
  
  <pre><code>List&lt;Employee&gt; list1 = Arrays.asList(new Employee(1, "Adam", "Smith", Type.CEO), new Employee(2, "Bob", "Jones", Type.OfficeManager), new Employee(3, "Carl", "Lewis", Type.SalesPerson));
  
  List&lt;Employee&gt; list2 = Arrays.asList(new Employee(4, "Xerxes", "Brown", Type.OfficeManager), new Employee(5, "Yuri", "Gagarin", Type.Janitor), new Employee(6, "Zain", "Wilson", Type.SalesPerson));
  </code></pre>
  
  <p>...and lets assume that I want to merge these lists into a new list by adding elements from both list1 and list2, but excluding elements that have an corresponding "identical" person object already added to the new list, and where the uniqueness is determined by the Type enum (Type.CEO, Type.OfficeManager etc).</p>
  
  <p>Then the expected result, after the merge, is a new list that contains the following persons:</p>
  
  <pre><code>Employee(1, "Adam", "Smith", Type.CEO)
  Employee(2, "Bob", "Jones", Type.OfficeManager)
  Employee(3, "Carl", "Lewis", Type.SalesPerson)
  Employee(5, "Yuri", "Gagarin", Type.Janitor)
  </code></pre>
  
  <p>What would be the "best" way to achieve this, in a general <strong>Java 8/9</strong> way? Ie I don't want to write something that is specific to Person objects or the Type enum, and I don't want to write something that uses the equals method of the objects. Instead I would like to use a <strong>BiPredicate</strong> or something similar.</p>
  
  <p>But also, I would like not having to perform any looping myself. <strong>Streams</strong> seems like a good choice, but I can't figure out how to achieve this. How can I write a BiPredicate where one value comes from one stream and the other value comes from another stream, without performing the looping myself?</p>
  
  <p>The reason I want to use an BiPredicate (or similar) is that I want to be able to use this function with advanced logic, where it is not possible to simply extract some property of all the elements, and then group the values based on the uniqueness of this property.</p>
  
  <p>Any suggestions?</p>
  
  <p>/Jimi</p>
  
  <p><strong><em>Update:</em></strong> To clarify why I talk about a predicate, here is a more complex example:</p>
  
  <p>Lets assume that we have the two collections of Employee objects as before. But this time the uniqueness logic can't be expressed using a mapping function to a specific property of the Employee object. Instead it uses some data in the EmployeeRegistry, like this: <em>if two employees belong to the same tax bracket <strong>or</strong> if they are of the same "type" then they are considered equal</em>. Because of this OR-logic it is not possible to reduce this to a unique key to use in grouping the data or something like that.</p>
  
  <p><strong><em>Update2</em></strong>: For the sake of simplicity, below is a less complex example, but that still is complex enough to not be a simple mapping to a field. It is a bit contrived, but that is for the sake of simplicity.</p>
  
  <p>Lets assume that we have the two collections of Strings. And uniqueness is calculated like this:</p>
  
  <ul>
  <li>If two strings are of equal length, they are considered equal</li>
  <li>Otherwise, if two strings start with the same character, they are considered equal</li>
  </ul>
  
  <p>Using the method <strong>Collectors.toMap</strong>, as suggested by <strong>Federico Peralta Schaffner</strong>, seems to work, although I'm not sure how I can write an <code>hashCode()</code> implementation that follows the standard and at the same time is efficient. The only functional implementation I can think of is one that returns a constant value (ie the same value regardless of the string).</p>
  
  <p><strong><em>Update 3</em></strong>: Considering that the <strong>OR-logic</strong> of my "equalness" algorithm breaks the <strong>equals contract</strong>, and makes it difficult (impossible?) to write an effective hashCode implementation, I am now back where I started. Ie needing something like a <strong>predicate</strong> of some sort. Here is an updated, "real world" example:</p>
  
  <p>Lets assume that we have the two collections of Employee objects as before, and we want to merge these collections into one. But this time we want to avoid including people that don't get along. To determin if two people get along, we have an HumanRelationsDepartment object, with the method isOkToWorkWithEachother(Person, Person). When two people that don't get along is detected, then only of of them is to be added to the new collection. Which one can be determined by a mapping function, and the default logic could be that the first person is selected.</p>
  
  <p>It is rather trivial to write old school code that solves this problem. What I'm looking for is a loop-free stream based solution. Does such a solution exist? Performance is not an issue.</p>