Дубликаты в строке - Java 8 лямбд - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь написать программу для печати дубликатов и подсчета в строке, используя Java 8 лямбда-символов, но получаю эту ошибку при попытке вставить значение в карту из списка. Может кто-нибудь, пожалуйста, помогите с тем, что не так. Сначала я преобразовал String в CharArray, а затем добавил в список, чтобы я мог выполнить внутреннюю итерацию по списку и проверить, существует ли уже значение в Map для хранения количества и каждого символа

import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;

public class PrintDuplicateInString {

 public static void main(String[] a) {
   printDuplicate("TestJava");
 }

 private static String printDuplicate(String s) {
    List<char[]> stringList = null;
    if(s != null && s.length() > 0) {
      char[] duplicateStr = s.toCharArray();
      stringList = Arrays.asList(s.toCharArray());
      TreeMap<Character,Integer> trmap = new TreeMap<>();
      stringList.forEach(i -> (trmap.containsKey(i))?(trmap.put(i,trmap.get(i)+1)):(trmap.put(i,1)));
    }
    stringList.forEach(System.out::println);
 }

}

Ответы [ 2 ]

3 голосов
/ 01 февраля 2020

Вместо использования List<char[]> вы можете хранить символы строки как:

List<Character> characters = s.chars()
                .mapToObj(e -> (char) e)
                .collect(Collectors.toList());

, дальнейшее нахождение частоты символов просто:

Map<Character, Long> trMap = characters.stream()
        .collect(Collectors.groupingBy(c -> c, Collectors.counting()));

в представлении, которое вы написали, это будет выглядеть так:

Map<Character, Long> trmap = new TreeMap<>();
for (Character c : characters) {
    if (trmap.containsKey(c)) {
        trmap.put(c, trmap.get(c) + 1);
    } else {
        trmap.put(c, 1L);
    }
}
0 голосов
/ 01 февраля 2020

Есть несколько проблем

  1. stringList - это List<char[]> (список массива символов), но вы на самом деле хотите List<Character> (список отдельных символов)
  2. Выражение trmap.containsKey(i) ? trmap.put(i, trmap.get(i)+1) : trmap.put(i,1) возвращает целочисленное значение, но .forEach не ожидает тип возвращаемого значения

Чтобы преобразовать String в список символов, необходимо выполнить List<Character> stringList = s.chars().mapToObj(c -> (char) c).collect(Collectors.toList());

Затем вы можете использовать более длинную форму if/else для вычисления количества:

stringList.forEach(i -> {
  if (trmap.containsKey(i)) {
      trmap.put(i, trmap.get(i) + 1);
  } else {
     trmap.put(i, 1);
 }
});

Если вы хотите использовать больше потоков, вы можете использовать Collections.toMap(..) коллектор

Map<Character,Integer> counts = s.chars().mapToObj(c -> (char) c)
.collect(Collectors.toMap(
   Function.identity(),
   c -> 1,
   (v1,v2) -> v1+v2
);

Что делают параметры toMap:

  1. Function.identity() говорит использовать текущий символ в потоке в качестве значения ключа
  2. c -> 1 говорит, чтобы сопоставить символ целочисленному значению 1 и сохранить его как значение на карте
  3. (v1,v2) -> v1+v2 Является функцией разрешения конфликтов. Поэтому, если мы обрабатываем поток и встречаемся с символьным ключом, который уже находится на карте, запустите эту функцию, чтобы вычислить обновленное значение для сохранения на карте. v1 представляет текущий счетчик на карте, v2 представляет 1, которому вы сопоставили символ во втором аргументе, поэтому v1+v2 вернет сумму этих двух чисел и сохранит ее на карте под персонаж. Это может быть далее сокращено как Integer::sum
...