First, we will build two maps: one for each list, matching names with objects. Then we iterate over the differences between the key sets, processing whatever type of object this name has. Maps allow you to avoid scanning in a list that searches for an object with this name. (When using Map, not Multimap, I rely on the respondentβs comment for another answer that the names in each list are unique. If you are still using Java 7, replace the method reference with the implementation of the function.)
Map<String, Object1> map1 = Maps.uniqueIndex(list1, Object1::getName); Map<String, Object2> map2 = Maps.uniqueIndex(list2, Object1::getName); for (String name : Sets.difference(map1.keySet(), map2.keySet())) processObject1(map1.get(name)); for (String name : Sets.difference(map2.keySet(), map1.keySet())) processObject2(map2.get(name));
If all you want to do is collect lists or sets of objects in only one list, processObject1 and processObject2 can simply add objects to collections.
uniqueIndex iteration order is the input iterable, and difference returns a SetView with the same iteration order as its first argument, so you can process the objects in the order they appear in the input lists, if that order is relevant to your problem.
Java 8 threads provide basically the same functionality:
Map<String, Object1> map1 = list1.stream().collect(Collectors.toMap(Function.identity(), Object1::getName)); Map<String, Object2> map2 = list2.stream().collect(Collectors.toMap(Function.identity(), Object2::getName)); map1.keySet().stream().filter(n -> !map2.keySet().contains(n)).map(map1::get).forEachOrdered(o1 -> processObject1(o1)); map2.keySet().stream().filter(n -> !map1.keySet().contains(n)).map(map2::get).forEachOrdered(o2 -> processObject1(o2));
Again, you can replace the forEachOrdered call with collect(Collectors.toList()) if you just want to collect the objects.