Найти только повторяющиеся строковые атрибуты в списке с Java 8 - PullRequest
0 голосов
/ 02 декабря 2018

Я знаю, что ниже приведен код для обнаружения вхождения каждого атрибута String в списке, как я могу отфильтровать этот список только с дублирующимся элементом, то есть с более чем 1 вхождением.Извините, я новичок в Java 8.

Map<String, Long> result = list.stream()
            .collect(Collectors.groupingBy(Function.identity(),
                                              Collectors.counting()));

Ответы [ 4 ]

0 голосов
/ 03 декабря 2018

Если ваш List является изменяемым, вы можете напрямую удалить все элементы, кроме их второго вхождения:

// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");

// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);

// example output
example.forEach(System.out::println);// prints bar baz

Приведенное выше решение сохраняет только одну копию для каждой строки, имеющей несколько вхождений, при удалении всех строк, не имеющихдубликаты.Если вы хотите сохранить все дубликаты и просто удалить те строки, которые не имеют дубликатов, сначала невозможно определить статус дубликата.

// same example input as above

// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);

// example output
example.forEach(System.out::println);// prints bar baz bar bar baz

Здесь временная карта может быть создана с помощью операции Stream ста же логика:

Map<String,Boolean> temp = example.stream()
    .collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
0 голосов
/ 02 декабря 2018

Более простой способ выяснить это может быть

List<String> recurringItems = list.stream()
        .filter(item -> list.lastIndexOf(item) != list.indexOf(item))
        .collect(Collectors.toList());

Поскольку для элементов, встречающихся более одного раза, lastIndex не будет равен первому индексу .


Кроме того, вы можете использовать Collectors.toSet(), чтобы гарантировать, что элементы перечислены только один раз, если вас не интересует их порядок повторения.

Set<String> recurringItemsOnce = list.stream()
        .filter(item -> list.lastIndexOf(item) != list.indexOf(item))
        .collect(Collectors.toSet());

Или использованиеCollections.frequency как:

Set<String> recurringItems = list.stream()
        .filter(item -> Collections.frequency(list, item) >= 2)
        .collect(Collectors.toSet());
0 голосов
/ 02 декабря 2018

Другой способ был бы таким.после groupBy удалите запись со значением = 1;

result = list.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
0 голосов
/ 02 декабря 2018

создайте поток из entrySet и filter:

List<Map.Entry<String, Long>> result =  list.stream()
                   .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                   .entrySet()
                   .stream()
                   .filter(s -> s.getValue() >= 2)
                   .collect(Collectors.toList());

или, если вы хотите сохранить карту, то:

Map<String, Long> result = stringList().stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .entrySet()
                .stream()
                .filter(s -> s.getValue() >= 2)
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

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

List<String> result = list.stream()
                .collect(Collectors.groupingBy(Function.identity(),
                        Collectors.counting()))
                .entrySet()
                .stream()
                .filter(x -> x.getValue() >= 2)
                .map(Map.Entry::getKey)
                .collect(toList());

другой вариант:

List<String> result = 
         list.stream()
             .filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
             .distinct()
             .collect(toList());
...