Случился затык. На вход подается текст, нужно подсчитать количество повторяющихся слов и вывести их в порядке от наиболее повторяющихся к наименее повторяющимся, затык в следующем. Как их можно отсортировать не только по количеству повторений, но и в лексикографическом порядке. (т.е. если есть два слова повторяющихся одинаковое число раз, отсортировать их в лексикографическом порядке).. Уже всю голову сломал .. Пока у меня получилось отсортировать только по количеству повторений..
List<String> list = new ArrayList<>();
BufferedReader inputLines = new BufferedReader(new InputStreamReader(inputStream, charset));
String wordsInText = inputLines.readLine();
Stream.of(wordsInText.split("[^A-Za-zА-Яа-я]+"))
.map(String::toLowerCase).forEach(p -> list.add(p));
Map<String, Long> countWords = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
countWords.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed()).forEach(System.out::println);
Можно так:
public static List<String> getRepeatedWordsSorted(String str) {
Enumeration<String> st = (Enumeration<String>)(Enumeration) new StringTokenizer(str);
Map<String, Integer> countMap = StreamSupport.stream(Spliterators.spliteratorUnknownSize(st.asIterator(), 0), false)
.collect(Collectors.toMap(v -> v, v -> 1, Integer::sum));
Map<Integer, Stream<String>> reverseCountMap = countMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, e -> Stream.of(e.getKey()), Stream::concat));
return reverseCountMap.entrySet().stream().sorted(Map.Entry.comparingByKey())
.map(e -> e.getValue().sorted()).flatMap(v -> v).collect(Collectors.toList());
}
Хотя соседний вариант с компаратором всё же лучше и с ним этот метод был бы таким:
public static List<String> getRepeatedWordsSorted(String str) {
Enumeration<String> st = (Enumeration<String>)(Enumeration) new StringTokenizer(str);
Map<String, Integer> countMap = StreamSupport.stream(Spliterators.spliteratorUnknownSize(st.asIterator(), 0), false)
.collect(Collectors.toMap(v -> v, v -> 1, Integer::sum));
return countMap.entrySet().stream().sorted((es1, es2) ->
es1.getValue().equals(es2.getValue()) ?
es1.getKey().compareTo(es2.getKey()) :
es1.getValue().compareTo(es2.getValue()))
.map(Map.Entry::getKey).collect(Collectors.toList());
}
Передаем свою лямбду как компаратор (меняется только последняя строка вашего кода):
countWords.entrySet().stream().sorted((item1, item2) ->
!item1.getValue().equals(item2.getValue()) ? // Если значения не одинаковы...
-item1.getValue().compareTo(item2.getValue()) : // то сравниваем по значениям (минус для обратного порядка)
item1.getKey().compareTo(item2.getKey())) // если одинаковы - то сравниваем ключи
.forEach(System.out::println);
Возможно будет понятнее, если расписать через if
:
countWords.entrySet().stream().sorted((item1, item2) -> {
if (!item1.getValue().equals(item2.getValue())) { // если значения не одинаковы...
return -item1.getValue().compareTo(item2.getValue()); // то сравниваем по значениям
} else {
return item1.getKey().compareTo(item2.getKey()); // если одинаковы - то по ключам
}
}).forEach(System.out::println);
запускаю 2 стрима, что не есть хорошо, но рефакторинг уже на вашей совести. на быструю руку примерно так:
BufferedReader inputLines = new BufferedReader(new InputStreamReader(inputStream, charset));
String wordsInText = inputLines.readLine();
Map<String, Long> result = Stream.of(wordsInText.split("[^A-Za-zА-Яа-я]+"))
.map(String::toLowerCase)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.sorted((e1, e2) -> {
final int compareResult = e2.getValue().compareTo(e1.getValue());
return compareResult != 0 ? compareResult : e1.getKey().compareTo(e2.getKey());
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> y, LinkedHashMap::new));
List<String> sortedList = Stream.of("13","13","23", "12", "12", "23")
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))//считаем элементы
.entrySet()//достаем пары слово-количество
.stream()
.sorted(Map.Entry.<String, Long>comparingByValue().thenComparing(Map.Entry.comparingByKey()))//сначала сортируем по количеству, если равны, то по значению (тут .reversed())
.map(Map.Entry::getKey)//достаем значения
.collect(Collectors.toList());//собираем
Реезультат [12, 13, 23]
Если есть желание отсортировать в порядке убывания, то можно использовать .reversed()
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Нужно что бы открывало ссылку на видео на сайте youtubecom перепробовал уже и xpath и Linktext и selector ничего не срабатывает вот код
В школе стоит программа-фильтрВ связи с этим после установки Android Studio (установилась вроде бы нормально) и создании первого проекта, не синхронизируется...
Здрасьте! Учу java, не могу решить одну проблему (пока что только одну)Пишу мелкий проект, для публикации арендовал удаленный комп на amazon, развернул...
Пытаюсь разобраться с многопоточностью в javaВот простенький код: