英文:
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<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";
}
}
}
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))));
}
});
这段代码可以简化,使用Map
的merge
方法:
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<String, List<String>> idToMap =
roles.stream()
.collect(Collectors.groupingBy(e -> e,
Collectors.mapping(e -> 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 -> {
if (idToMap.containsKey(role)) {
idToMap.get(role).add(getName(role));
} else {
idToMap.put(role, new ArrayList<>(Arrays.asList(getName(role))));
}
});
which can be simplified using Map
's merge
method
roles.forEach(
role -> idToMap.merge(role, new ArrayList<>(Arrays.asList(getName(role))), (a, b) -> {
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<String, Integer>
roles.stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()))
.entrySet()
.forEach(e -> {
if (e.getValue() > 1) {
System.out.println("found a key which has duplicate value : " + e.getKey());
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论