Как написать строковую итерацию с операциями Map Put в Java 8?

#string #lambda #java-8 #hashmap

#строка #лямбда #java-8 #hashmap

Вопрос:

Я пытаюсь преобразовать следующий код в Java 8::

 String s = "12345";
Map<Character,Integer> map = new HashMap<Character,Integer>();
for (int i = 0; i < s.length(); i  ) {
 char c = s.charAt(i);
 if (map.containsKey(c)) {
   int cnt = map.get(c);
   map.put(c,   cnt);
 } else {
   map.put(c, 1);
 }
}
 

Я попробовал и нашел следующий способ итерации:

 IntStream.rangeClosed(0, s.length).foreach(d -> {
      //all statements from char to map.put
}) ;
 

Я не уверен, правильно ли это сделать.

Комментарии:

1. Или использовать toMap с функцией слияния: s.chars().mapToObj(i->(char)i).collect(Collectors.toMap(Function.identity(),v->1,Integer::sum));

2. Подумайте о том, чтобы остаться в цикле : for(int i = 0; i < s.length(); i ) map.merge(s.charAt(i), 1, Integer::sum); . Конечно, вы также можете использовать IntStream.range(0, s.length()) .forEach(i -> map.merge(s.charAt(i), 1, Integer::sum)); вместо. Но это не реальное улучшение.

Ответ №1:

Вы можете сделать это:

 s.chars()
  .mapToObj(x -> (char) x)
  .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
 
  • .mapToObj(x -> (char) x) необходимо, потому .chars() что дает вам поток целых чисел, но для использования groupingBy вам нужно работать с объектами, а не с примитивами
  • groupingBy получает функцию для получения ключа для group by и Collector реализации
  • Function.identity() это просто функция, которая возвращает любой элемент, который ей передается
  • Collectors.counting() является ли коллектор, который имеет значение

Комментарии:

1. Имейте в виду, что это создаст Map<Character,Long> . Вам нужно, например Collectors.summingInt(ch -> 1) , вместо Collectors.counting() того, чтобы получить Map<Character,Integer> .

2. Хорошо, я не знал об этом методе. Спасибо!

Ответ №2:

Вы можете использовать сборщики groupingBy() and counting() :

 String s = "12345";

Map<Character, Long> map = s
        .chars()
        .mapToObj(i -> (char) i)
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

System.out.println(map);
 

К сожалению, кажется, что нет удобного способа получить a Stream<Character> из строки, следовательно, необходимо сопоставить с IntStream using chars() , а затем использовать mapToObj() для преобразования его в поток символов.