Страницы

Поиск по вопросам

пятница, 9 ноября 2018 г.

Подсчет количества вхождений букв в строку с помощью потока (Stream)

Есть определенная строка(например "Some example"). Нужно определить количество вхождений каждой буквы в строке с помощью потока Stream и при этом без использования циклов, if и прочего(лишь рекурсия, потоки Stream и его методы вроде map, reduce, filter).
Я сделал из строки массив символов, который потом превратил в список c помощью рекурсивного метода toCharList.
String text = "Some example".toLowerCase.replaceAll("\\s", "") List textInChar = toCharList(text.toCharArray(), 0);
static public List toCharList(char[] textChars, int i) {
if(textChars.length == i) return new ArrayList<>();
List ret = new ArrayList<>(); ret.add(textChars[i]); ret.addAll(toCharList(textChars, i + 1));
return ret; }
Затем из этого списка создал хэш-мапу c помощью перегруженного метода toCharMap. Таким образом получил я список всех не повторяющихся букв, которые есть в строке.
Map countChar = toCharMap(textInChar);
public static Map toCharMap(List l) { return toCharMap(l.iterator()); }
public static Map toCharMap(Iterator it) { if (!it.hasNext()) return new HashMap<>();
Map ret = new HashMap<>(); ret.put((Character)it.next(), 0); ret.putAll(toCharMap(it));
return ret; }
Но как теперь их посчитать в потоке, например с помощью filter и reduce?


Ответ

1) Из строки массив символов лучше получать так:
String text = ("Some example").toLowerCase().replaceAll("\\s", ""); List textInChar = Chars.asList(text.toCharArray());
или:
textInChar = text.chars().mapToObj(e->(char)e).collect(Collectors.toList());
2) Xэш-мапу не повторяющихся символов лучше получить тогда уж так:
Map countChar = textInChar.stream().collect(HashMap::new, (m, c) -> { m.put(c, 1); m.put(c, 1); }, HashMap::putAll);
А всю задачу я бы решил так:
textInChar = text.chars().mapToObj(e->(char)e).collect(Collectors.toList()); Map countChar = textInChar.stream().collect(HashMap::new, (m, c) -> { if(m.containsKey(c)) m.put(c, m.get(c) + 1); else m.put(c, 1); }, HashMap::putAll);
Проверим:
countChar.forEach( (k, v) -> LOG.debug(k + " -> " + v));
Выведет:
p -> 1 a -> 1 s -> 1 e -> 3 x -> 1 l -> 1 m -> 2 o -> 1
UPD:
if(m.containsKey(c)) m.put(c, m.get(c) + 1); else m.put(c, 1);
Можно сократить до:
m.put(c, m.containsKey(c) ? (m.get(c) + 1) : 1);

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

Отправить комментарий