#java #java-stream
#java #java-stream
Вопрос:
Я пытаюсь написать программу, которая находит повторяющееся значение в map, и эта карта создается с использованием методов list и utiity.
Я могу получить ожидаемый результат, используя цикл for, но код слишком длинный, используя это.
Я попытался использовать Java stream 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 Stream API
Комментарии:
1.
roles.stream().map(role -> {...
я думаю, что этот фрагмент кода вообще не будет выполнен, можете ли вы, пожалуйста, проверить Bhavya?2. Ваш ожидаемый результат отличается от того, что вы на самом деле хотите напечатать. Вы действительно хотите сопоставить с
List<String>
типом значения вMap
или для вас достаточно частоты появления?
Ответ №1:
Вы можете использовать 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("found a key which has duplicate value : " e.getKey());
}
});
Комментарии:
1. спасибо за ваш ответ! Могу ли я также объединить
idToMap.entrySet().forEach(e-> { if(e.getValue().size()>1) { System.out.println("found a key which has duplicate value : " e.getKey()); } });
сroles.stream().map()
?2. Да, просто добавьте цепочку
roles.stream().collect(Collectors.groupingBy(e -> e, Collectors.mapping(e -> getName(e), Collectors.toList()))).entrySet().forEach(...)
3. код, который вы упомянули above..is работает как шарм 😃 .. Не могли бы вы, пожалуйста, объяснить это вкратце, и тогда я приму ответ
4. @BhavyaGupta Можете ли вы сказать, какую часть вы не понимаете? Я попытаюсь объяснить об этом 🙂
5. первый, который вы используете
Collectors.groupingBy
, но я думаю, что теперь это немного понятнее 🙂 Принят ваш ответ 🙂