I have a object class like
class Device{ String name; String type; String status; }
I have 2 lists
1st one is like
{d1,m1,active}, {d2,m2,active},{d3,m3,acticve}
2nd one {d2,m2,paused},{d4,m4,paused}
i want my final list to be like
{d1,m1,active},{d2,m2,paused},{d3,m3,active},{d4,m4,paused}
My approach was to make a list of commonName{d2}
then add both the list{d1,d2,d2,d3,d4}
into a total list and then iterate through the total list and if the common deviceName(d2.contains(i.getName())
) matches then remove the one with the status active(By remove i mean make another list and dont add the “Active” object).
Is there an efficient way of doing this other than using contains inside a iteration. Reducing the complexity to o(N).
Advertisement
Answer
Assuming the divices in first list have unique names you can stream over both list and collect to map merging whenever found same name in second list chosing the one having paused
as status. Example using following class as sample:
@ToString @AllArgsConstructor @Getter static class Divice { private String name; private String type; private String status; }
and following sample lists
List<Divice> list1 = new ArrayList<>(); list1.add(new Divice("d1", "m1", "active")); list1.add(new Divice("d2", "m2", "active")); list1.add(new Divice("d3", "m3", "active")); List<Divice> list2 = new ArrayList<>(); list2.add(new Divice("d2", "m2", "paused")); list2.add(new Divice("d4", "m4", "paused"));
then do :
List<Divice> merged = new ArrayList<>( Stream.concat(list1.stream(),list2.stream()) .collect(Collectors.toMap(Divice::getName, Function.identity(), (i,j) -> "paused".equals(i.getStatus()) ? i : j, LinkedHashMap::new)).values() ); merged.forEach(System.out::println);