Khaled Alhayek
Khaled Alhayek

Reputation: 583

Update list of object from another list keeping the order using lambda expressions in Java 8

I have two lists of objects. The object is a simple class contains key, value attributes.

I want to update the value of the first list from the second one. Replacing or cloning the list is not working because the ordering of the two lists are different and they should stay in their orders.

Any suggestions?

Example:

for(int i = 0 ; i < mValues.size() ; i++)
        {
            for (int j = 0 ; j < mValues.size() ; j++)
            {
                if(newData.get(i).getKey().equalsIgnoreCase(mValues.get(j).getKey()))
                {
                    mValues.get(j).setValue(newData.get(i).getValue());
                }
            }

        }

Demo:

myObject o1 = new myObject("k1" , 10);
myObject o2 = new myObject("k2" , 20);
myObject o3 = new myObject("k2" , 30);
myObject o4 = new myObject("k1" , 40);

List<myObject> l1 = new ArrayList<>();
List<myObject> l2 = new ArrayList<>();
l1.add(o1);
l1.add(o2);

l2.add(o3);
l2.add(o4);

Here should make the update to l1 based on l2 by looking for the key and update the value.

The result should look like:

Upvotes: -1

Views: 5988

Answers (2)

Oboe
Oboe

Reputation: 2723

I would use streams for that job.

Assuming your class MyObject has getters and setters methods defined (getKey(), getValue(), setKey(), setValue()), you can do:

l1.forEach(myObject1 -> l2.stream()
            .filter(myObject2 -> myObject1.getKey().equals(myObject2.getKey()))
            .findAny().ifPresent(myObject2 -> myObject1.setValue(myObject2.getValue())));

If you can have duplicate keys then you should modify ifPresent() to forEach():

l1.forEach(myObject1 -> l2.stream()
            .filter(myObject2 -> myObject1.getKey().equals(myObject2.getKey()))
            .forEach(myObject2 -> myObject1.setValue(myObject2.getValue())));

Upvotes: 2

PatrickChen
PatrickChen

Reputation: 1430

Not many elegant one line streaming I can think of. My suggestion is split two steps:

  1. convert l2 to map.
  2. stream map change items in l1. This is more flexible and easy to debug solution.
static class myObject {
    String key;
    int val;

    public myObject(String key, int val) {
      this.key = key;
      this.val = val;
    }

    @Override
    public String toString() {
      return "myObject{" +
          "key='" + key + '\'' +
          ", val=" + val +
          '}';
    }
  }
  public static void main(String[] args) {
    myObject a = new myObject("k1", 30);
    myObject b = new myObject("k2", 40);
    Map<String, myObject> list2map = List.of(a,b).stream().collect(Collectors.toMap(m -> m.key, m -> m));

    myObject c = new myObject("k1", 10);
    myObject d = new myObject("k2", 20);
    List<myObject> l1 = List.of(c, d);
    l1 = l1.stream().map(m -> {
      m.val = list2map.getOrDefault(m.key, m).val;
      return m;
    }).collect(Collectors.toList());
    System.out.println(l1);
  }

Upvotes: 1

Related Questions