简体   繁体   中英

Efficient way how to check differences between two collections in Java

I am having a List of strings {1,2,7}

Now I have a new List : {2,4,9}

Rules are simple:

  1. if element on List A doesn't exist on List B we add it to new delete-list
  2. if element on List B doesn't exist on List A we add it to new create-list
  3. if element exists on both lists we don't touch it

so the outcome is two new lists:

delete list: {1,7}

create list: {4,9}

Any idea how to make it efficient within java? perhaps using Java8 to make it easier?

My lists have about 1000 elements.

delete_list = A.copy();
create_list = B.copy();
delete_list.stream().removeIf(e -> B.contains(e));
create_list.stream().removeIf(e -> A.contains(e));

Basically we just create two distinct list. In set theory we can write the output like this:

delete_list = A \\ B
create_list = B \\ A

Thanks @SashaSalauyou for calling my attention on a mistake i made.

If ordering is not important, use Set bulk operations:

Set<String> a = new HashSet<>(Arrays.asList("1", "2", "7"));
Set<String> b = new HashSet<>(Arrays.asList("2", "4", "9"));

Set<String> deleteSet = new HashSet<>(a);
deleteSet.removeAll(b);                   // [1, 7]
Set<String> createSet = new HashSet<>(b);
createSet.removeAll(a);                   // [4, 9]

If you want Java 8, just filter elements and collect:

List<String> deleteList = a.stream().filter(e -> !b.contains(e)).collect(Collectors.toList());
List<String> createList = b.stream().filter(e -> !a.contains(e)).collect(Collectors.toList());

Here, a and b could be lists, but it is highly recommended to make them Set s since contains() operation is O(n) in most list implementations.

Though not very elegant solution but we can also use Streams in Java8:

Set<String> setOne = new HashSet<>(Arrays.asList("1","2","7"));
Set<String> setTwo = new HashSet<>(Arrays.asList("2","4","9"));
System.out.println(setOne.stream().filter(i-> !setTwo.contains(i)).collect(Collectors.toList()));
System.out.println(setTwo.stream().filter(i-> !setOne.contains(i)).collect(Collectors.toList()));

It prints:

[1, 7] [4, 9]

One important point is that setOne and setTwo should be effectively final to work in a lambda expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM