10

I have 2 lists:

  1. List1<Object1>: Object1 (name1, id1)
  2. List2<Object2>: Object2 (name2, id2)

The size of list1 is the same as list2.

I want to iterate over list2 and if the name2 of list2 is not null, then update the name1 of list1.

Jere is the code using old Java:

  for(Object1 obj1:list1) {
    for(Object2 obj2:list2) {
      if(obj1.getId1.equals(obj2.getId2)) {
        obj1.setName1(obj2.getName2);
      }
   }
}

Which is the best way to implement this with java.util.stream?

3
  • Currently, your code has quadratic complexity. Do you actually want to check all combinations of elements, or only elements at the same index of their respective list? Commented Feb 15, 2016 at 11:43
  • 1
    Does id mean a unique identifier for your objects? In that case a map with the id as a key is more appropriate than a list. It would also reduce time complexity to O(n) (in case of a HashMap) instead of O(n^2). Commented Feb 15, 2016 at 11:52
  • Yes id is a unique identifier for object. Commented Feb 15, 2016 at 13:07

3 Answers 3

17

Just to be clear, I think your code is intended to do the following: update the name of each item in list1 to be the name of any item in list2 that has the same ID. There doesn't seem to be anything checking if the names of items in list1 are null.

If that's correct, then:

list2.forEach(obj2 -> list1.stream()
     .filter(obj1 -> obj1.getId().equals(obj2.getId()))
     .forEach(obj1 -> obj1.setName(obj2.getName()));

If you want to check if name is null, then add a new filter before setting the name:

    .filter(Objects::isNull)
Sign up to request clarification or add additional context in comments.

Comments

6

As I mentioned in the comments. If the id is a uniqe identifier for your objects, then a Map is more appropriate than a List.

So you better work on such a map (assuming id is an integer):

Map<Integer, Object1> obj1map;

You could create that map from your first list with

obj1map = list1.stream().collect(toMap(Object1::getId, Function.identity()));

Now you can stream over your second list and update the map accordingly:

list2
    .stream()
    .filter(o -> o.getName() != null) // remove null names
    .filter(o -> obj1map.containsKey(o.getId())) // just to make sure
    .forEach(o -> obj1map.get(o.getId()).setName(o.getName()));

Comments

-2

The idea of a stream is that it does not have context. Knowing where you are in the first stream is context which you would need to find the corresponding item in the second stream.

Use a normal for loop with an index i instead.

for (int i=0; i < list2.size(); i++) {
  Object2 item2 = list2.get(i);
  if (list2.get(i).name != null) {
    list1.get(i).name = item.name;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.