重复Java 8流

时间:2017-11-08 16:53:47

标签: java collections java-8 java-stream

Java 8在这里。我有一个方法checkDupeKeys,它将三个不同的SortedMap实例作为其参数,并需要验证没有两个SortedMap实例具有相同的键。到目前为止我最好的尝试:

private void checkDupeKeys(SortedMap<String, Fizz> fizzes, SortedMap<String, Buzz> buzzes,
        SortedMap<String, Foobar> foobars) {}
    List<String> keyNames = new ArrayList<>();

    keyNames.addAll(fizzes.keySet().stream().collect(Collectors.toList()));
    keyNames.addAll(buzzes.keySet().stream().collect(Collectors.toList()));
    keyNames.addAll(foobars.keySet().stream().collect(Collectors.toList()));

    if(keyNames.size() > keyNames.stream().collect(Collectors.toSet()).size()) {
        throw new IllegalArgumentException("Duplicate key names are not allowed.");
    }
}

相信这是有效的,但是很可能有更好的方法(效率等)。

我主要担心的是,这种方法不允许我识别哪些键名是重复的。我理想地喜欢异常消息:

Duplicate key names are not allowed. You have the following duplicate key names: (1) fizzes["derp"] and buzzes["derp"]. (2) fizzes["flim"] and foobars["flim"]. (3) buzzes["flam"] and foobars["flam"].

如何修改我的(非静态)checkDupeKeys方法以抛出符合此条件的异常?也就是说,如何访问流中的哪些键是彼此重复的。我确信我可以使用旧的Java集合API来实现 hard way ,但在此解决方案中,效率和利用Java 8 API对我来说非常重要。

2 个答案:

答案 0 :(得分:1)

如果没有太多使用Java 8的功能习惯用法,我只需使用Set#retainAll进行每次比较(总共3个)。

见下面的草案代码:

private void checkDupeKeys(SortedMap<String, Fizz> fizzes, 
    SortedMap<String, Buzz> buzzes, 
    SortedMap<String, Foobar> foobars) {

    // copies the key set
    Set<String> fizBuzSet = new HashSet<>(fizzes.keySet());

    // this removes all elements of the set that aren't present in the given key set
    fizBuzSet.retainAll(buzzes.keySet());

    // aggregating dupes if needed
    Map<String, Collection<String>> dupes = new HashMap<>();
    // flag to throw exception if needed
    boolean areThereDupes = false;

    if (!fizBuzSet.isEmpty()) {
        areThereDupes = true;
        // TODO log fizBuzSet as set of duplicates between fizzes and buzzes
        // or...
        dupes.put("Fizzes vs Buzzes", fizBuzSet);
    }
    // TODO repeat with fizzes vs foobars, then again with buzzes vs foobars

    // you can either log the dupes separately, or use a Map<String,Collection<String>> where the  
    // keys represent a compound of the two SortedMaps being compared and the values represent the actual duplicates  
    // e.g...
    if (areThereDupes) {
        // TODO throw exception with dupes map representation in message
    }

}

答案 1 :(得分:0)

您要做的第一件事就是将所有密钥收集到一个流中:

 Stream<String> keys = Stream.of(
       fizzes.keySet().stream(), 
       buzzes.keySet().stream(), 
       foobars.keySet().stream())
    .flatMap(s -> s);

现在你可以collect将它们变成计数图:

 Map<String, Long> counts = keys.collect(
     Collectors.groupingBy(Function.identity(),
     Collectors.counting()));

您可以使用计数&gt;过滤条目1:

 Set<String> duplicates = counts.entrySet().stream()
            .filter( e -> e.getValue() > 0)
            .map(Entry::getKey)
            .collect(Collectors.toSet());

如果此设置不为空,则抛出异常。