使用Java Stream API查找映射中的重复值。

huangapple go评论77阅读模式
英文:

Find duplicate value in map using Java Stream API

问题

以下是翻译好的部分:

我正在尝试编写一个程序,该程序可以在映射中找到重复的值,而此映射是使用列表和实用方法创建的。

我能够使用for循环获得预期的输出,但是那样的代码太长了。

我尝试使用Java流API,如下所示,但得到了空结果。

public class PrintListElements {
    public static void main(String[] args) {
        List<String> roles = new ArrayList<>();
        roles.add("1");
        roles.add("2");
        roles.add("3");
        roles.add("4");
        roles.add("5");
        roles.add("6");
        roles.add("7");
        roles.add("1");
        HashMap<String, List<String>> idToMap = new HashMap<>();
        roles.stream().map(role -> {
            if (idToMap.containsKey(role)) {
                return idToMap.get(role).add(getName(role));
            } else {
                return idToMap.put(role, new ArrayList<>(Arrays.asList(getName(role))));
            }
        })

        idToMap.entrySet().forEach(e-> {
            if(e.getValue().size()>1) {
                System.out.println("found a key which has duplicate value : "+ e.getKey());
            }
        });

    }

    public static List<String> getNameLL(String id) {
        ArrayList<String> ll = new ArrayList<String>();
        ll.add(getName(id));
        return ll;
    }

    public static String getName(String id) {
        switch (id) {
            case "1":
                return "one";
            case "2":
                return "two";
            case "3":
                return "third";
            case "4":
                return "four";
            case "5":
                return "fifth";
            case "6":
                return "six";
            case "7":
                return "seven";
            case "8":
                return "one";
            default:
                return "one";
        }
    }
}

预期输出:

[one, one]
[two]
[three]
[four]
[five]
[six]
[seven]

请问是否有人可以帮助我,使用Java流API获得上述预期的输出结果

英文:

I am trying to write a program that finds the duplicate value in map, and this map is created using the list and utiity methods.

I am able to get the expected output using for loop, but the code is too long using that.

I tried using the java stream API as shown below, but got empty results.

public class PrintListElements {
public static void main(String[] args) {
List&lt;String&gt; roles = new ArrayList&lt;&gt;();
roles.add(&quot;1&quot;);
roles.add(&quot;2&quot;);
roles.add(&quot;3&quot;);
roles.add(&quot;4&quot;);
roles.add(&quot;5&quot;);
roles.add(&quot;6&quot;);
roles.add(&quot;7&quot;);
roles.add(&quot;1&quot;);
HashMap&lt;String, List&lt;String&gt;&gt; idToMap = new HashMap&lt;&gt;();
roles.stream().map(role -&gt; {
if (idToMap.containsKey(role)) {
return   idToMap.get(role).add(getName(role));
} else {
return idToMap.put(role, new ArrayList&lt;&gt;(Arrays.asList(getName(role))));
}
})
idToMap.entrySet().forEach(e-&gt; {
if(e.getValue().size()&gt;1) {
System.out.println(&quot;found a key which has duplicate value : &quot;+ e.getKey());
}
});
}
public static List&lt;String&gt; getNameLL(String id) {
ArrayList&lt;String&gt; ll = new ArrayList&lt;String&gt;();
ll.add(getName(id));
return ll;
}
public static String getName(String id) {
switch (id) {
case &quot;1&quot;:
return &quot;one&quot;;
case &quot;2&quot;:
return &quot;two&quot;;
case &quot;3&quot;:
return &quot;third&quot;;
case &quot;4&quot;:
return &quot;four&quot;;
case &quot;5&quot;:
return &quot;fifth&quot;;
case &quot;6&quot;:
return &quot;six&quot;;
case &quot;7&quot;:
return &quot;seven&quot;;
case &quot;8&quot;:
return &quot;one&quot;;
default:
return &quot;one&quot;;
}
}
}

Expected Output:

[one, one]
[two]
[three]
[four]
[five]
[six]
[seven]

Can anyone please help me, to get the above-expected output result using Java Stream API

答案1

得分: 4

你可以使用Collectors.groupingBy按键分组,使用Collectors.mapping映射值并收集为每个键的列表。

Map<String, List<String>> idToMap = 
    roles.stream()
         .collect(Collectors.groupingBy(e -> e, 
                      Collectors.mapping(e -> getName(e), Collectors.toList())));

或者,map操作是惰性的,所以.map内部的代码不会被执行。你可以通过重构你当前的代码,使用像forEach这样的终端操作:

roles.forEach(role -> {
    if (idToMap.containsKey(role)) {
       idToMap.get(role).add(getName(role));
    } else {
       idToMap.put(role, new ArrayList<>(Arrays.asList(getName(role))));
    }
});

这段代码可以简化,使用Mapmerge方法:

roles.forEach(
    role -> idToMap.merge(role, new ArrayList<>(Arrays.asList(getName(role))), (a, b) -> {
      a.addAll(b);
      return a;
    }));

更新: 如果你只想要打印重复值,你可以使用Collectors.counting()来获得键的频率,将结果收集为Map<String, Integer>

roles.stream()
     .collect(Collectors.groupingBy(e -> e, Collectors.counting()))
     .entrySet()
     .forEach(e -> {
          if (e.getValue() > 1) {
            System.out.println("找到一个具有重复值的键:" + e.getKey());
          }
      });
英文:

You can use Collectors.groupingBy to group by key and use Collectors.mapping to map values and collect as a list for each key.

Map&lt;String, List&lt;String&gt;&gt; idToMap = 
roles.stream()
.collect(Collectors.groupingBy(e -&gt; e, 
Collectors.mapping(e -&gt; getName(e), Collectors.toList())));

Or map operation is lazy, so code inside .map is not executed. You can use terminal operation like forEach by refactoring your current code,

roles.forEach(role -&gt; {
if (idToMap.containsKey(role)) {
idToMap.get(role).add(getName(role));
} else {
idToMap.put(role, new ArrayList&lt;&gt;(Arrays.asList(getName(role))));
}
});

which can be simplified using Map's merge method

roles.forEach(
role -&gt; idToMap.merge(role, new ArrayList&lt;&gt;(Arrays.asList(getName(role))), (a, b) -&gt; {
a.addAll(b);
return a;
}));

Update: If you want just print for duplicate value, you can use Collectors.counting() to get the frequency of key as a result collect as Map&lt;String, Integer&gt;

roles.stream()
.collect(Collectors.groupingBy(e -&gt; e, Collectors.counting()))
.entrySet()
.forEach(e -&gt; {
if (e.getValue() &gt; 1) {
System.out.println(&quot;found a key which has duplicate value : &quot; + e.getKey());
}
});

huangapple
  • 本文由 发表于 2020年9月4日 20:26:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63741164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定