检查整数列表是否包含两组不同的重复数字

Check if list of integers contains two groups of different repeated numbers

如何使用 java 流,检查整数列表是否包含两组不同的重复数字。数字必须重复不超过两次。

示例:23243 列表。
答:是的,因为 2233

示例 2:23245 的列表。
答案:none

示例 3:23232 的列表。
答案:none,因为222重复了三次

还有一个问题,如何才能return不是anyMatch,而是最大的重复数呢?

listOfNumbers.stream().anyMatch(e -> Collections.frequency(listOfNumbers, e) == 2)

这将告诉您列表是否符合您的要求。

  • 流式传输数字列表。
  • 计算频率。
  • 流式传输结果计数
  • 过滤掉那些不等于 2 的计数。
  • 然后数一数其中有多少。

Returns 如果 final count == 2 则为真,否则为假。

List<Integer> list = List.of(2,2,3,3,3,4,4);
boolean result = list.stream()
        .collect(Collectors.groupingBy(a -> a,
                Collectors.counting()))
        .values().stream().filter(count -> count == 2).limit(2)
        .count() >= 2;  // fixed per OP's comment

上面打印 true 因为有两组只有两个数字,即 2's4's

编辑

首先,我提出了 Holger's 短路计数检查的建议。

为了解决您关于 returning 多个值的问题,我将流程分成了几个部分。第一个是我之前做的正常频率计数。接下来是收集所要求的信息。我用了一个record到return的信息。 class 也可以。某些特定数字的最大计数位于 AbstractMap.SimpleEntry

List<Integer> list = List.of(2, 3, 3, 3, 4, 4, 3, 2, 3);
Results results = groupCheck(list);
System.out.println(results.check);
System.out.println(results.maxEntry);

打印(getKey()getValue() 可用于获取单个值。第一个是数字,第二个是该数字的出现次数。)

true
3=5  

方法和记录声明

record Results(boolean check,
        AbstractMap.SimpleEntry<Integer, Long> maxEntry) {
}

计算频率计数后,只需遍历条目并 通过将现有的最大计数与迭代的最大计数进行比较并根据需要进行更新来计算对数并计算 maxEntry。


public static Results groupCheck(List<Integer> list) {
    Map<Integer, Long> map = list.stream().collect(
            Collectors.groupingBy(a -> a, Collectors.counting()));
    
    AbstractMap.SimpleEntry<Integer, Long> maxEntry =
            new AbstractMap.SimpleEntry<>(0, 0L);
    int count = 0;
    for (Entry<Integer, Long> e : map.entrySet()) {
        if (e.getValue() == 2) {
            count++;
        }
        maxEntry = e.getValue() > maxEntry.getValue() ?
                new AbstractMap.SimpleEntry<>(e) : maxEntry;
    }
    
    return new Results(count >= 2, maxEntry);
}

可以编写一个方法来构建 TreeMap 个频率。

这里发生的事情是,首先构建一个频率图(通过 groupingBy(Function.identity(), Collectors.counting()))),然后我们必须 'swap' 键和值,因为我们想使用频率作为键。

public static TreeMap<Long, List<Integer>> frequencies(List<Integer> list) {
    return list.stream()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        .entrySet().stream()
        .collect(Collectors.toMap(e -> e.getValue(), e -> List.of(e.getKey()), (a, b) -> someMergeListsFunction(a, b), TreeMap::new));
    }

然后我们可以像这样使用我们的方法:

// We assume the input list is not empty
TreeMap<Long, List<Integer>> frequencies = frequencies(list);
var higher = frequencies.higherEntry(2L);
if (higher != null) {
    System.out.printf("There is a number which occurs more than twice: %s (occurs %s times)\n", higher.getValue().get(0), higher.getKey());
}
else {
    List<Integer> occurTwice = frequencies.lastEntry().getValue();
    if (occurTwice.size() < 2) {
        System.out.println("Only " + occurTwice.get(0) " occurs twice...");
    }
    else {
        System.out.println(occurTwice);
    }
}

A TreeMap 是一个 Map,键由一些比较器排序,或者 自然顺序 如果给出 none。 TreeMap class 包含搜索特定键的方法。例如,higherEntry 方法 returns 高于给定键的第一个条目。使用这种方法,你可以很容易地检查是否存在高于2的键,因为其中一个要求是none的数字可能出现两次以上。

上面的代码检查是否有数字出现超过两次,即 higherEntry(2L) returns 非空值。否则,lastEntry() 是出现的最高数字。使用 getValue(),您可以检索这些号码的列表。