Сравнение двух больших списков (более 1 лакха) в Java - PullRequest
0 голосов
/ 25 июня 2019

Я хочу сравнить два больших списка строк в Java, которые не имеют одинаковый размер.Я хочу знать, есть ли лучший способ улучшить производительность.

Я вижу проблему с производительностью в

List<String> list1 = 100k records 
List<String> list2 = 10 million records;

#method1 used removeAll
list1.removeAll(list2);

method2 used java8 streams
List<String> unavailable = list1.stream()
                    .filter(e -> (list2.stream()
                            .filter(d -> d.equals(e))
                            .count())<1)
                            .collect(Collectors.toList());

Примечание: я пытаюсь получить записи, которые находятся в списке list1 и не существует в списке list2.

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Единственное, что вы можете сделать для улучшения производительности, это использовать Set с вместо List с, потому что они имеют O (1) для Set.contains(). Но поэтому вы не должны заботиться о дубликатах в ваших списках.

Если вы не заботитесь о порядке товаров, используйте HashSet, в противном случае используйте LinkedHashSet. При использовании наборов почти не имеет значения, используете ли вы Set.removeAll() или Stream.filter(), потому что removeAll() использует contains() внутри.

Так что вы можете использовать это, если вам нужен новый набор и не хотите прикасаться к оригиналу:

Set<String> set2 = new HashSet<>(list2);
Set<String> unavailable = list1.stream()
        .filter(e -> !set2.contains(e))
        .collect(Collectors.toSet());

Если вы хотите получить список как результат, используйте Collectors.toList() вместо:

Set<String> set2 = new HashSet<>(list2);
List<String> unavailable = list1.stream()
        .filter(e -> !set2.contains(e))
        .collect(Collectors.toList());

Используйте это, если вы просто хотите удалить элементы из list1:

Set<String> set2 = new HashSet<>(list2);
list1.removeAll(set2);

или еще короче:

list1.removeAll(new HashSet<>(list2));
0 голосов
/ 25 июня 2019
List<String> unavailable = list1.stream()
                                .filter(e -> !list2.contains(e))
                                .collect(Collectors.toList());

(или)

List<String> unavailable = list1.stream() 
                                .filter(not(list2::contains)) 
                                .collect(Collectors.toList());

создать предикат, как показано ниже

public static <T> Predicate<T> not(Predicate<T> t) {
        return t.negate();
    }
...