Найти повторяющееся значение на карте с помощью Java Stream API

#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 , но я думаю, что теперь это немного понятнее 🙂 Принят ваш ответ 🙂