使用Java 8在列表中仅查找重复的String属性

时间:2018-12-02 19:51:52

标签: java java-8 java-stream

我知道以下是找出list中每个String属性的出现的代码,如何仅使用重复项(即出现多次)过滤该列表。抱歉,我是Java 8的新手。

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

4 个答案:

答案 0 :(得分:6)

entrySetfilter创建流:

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());

答案 1 :(得分:6)

如果您的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);

答案 2 :(得分:4)

另一种方式是这样的。在groupBy之后,然后删除值= 1的条目;

result = list.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);

答案 3 :(得分:1)

一种更简单的发现方法可能是

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());