我有一个单词列表,比如说
List<String> words = Arrays.asList("Hello alan i am here where are you"+
"and what are you doing hello are you there");
如何按降序排列列表中重复多次的前七个单词?然后单个输入词应按字母顺序排列。所以上面的输出应该是前七个单词
you (3)
are (2)
hello (2)
alan (1)
am (1)
and (1)
doing (1)
我希望在Java 8中使用流,lamda。
我正在尝试这种方式。 首先对列表进行排序 其次,在单词列表中获取单词的映射。
List<String> sortedWords = Arrays.asList("Hello alan i am here where are you and what are you doing hello you there".split(" "))
.stream().sorted().collect(toList());
Map<String, Long> collect =
sortedWords.stream().collect(groupingBy(Function.identity(), counting()));
答案 0 :(得分:9)
最困难的部分是分拣。由于您只想保留结果中的7个第一个元素,并且您希望按照其值对Map进行排序,我们需要创建所有结果的Map,对其进行排序,然后保留7个结果。
在下面的代码中,每个单词都是低位的,并按自己分组,计算出现的次数。然后,我们需要对这个映射进行排序,以便我们在条目上创建一个Stream,根据值(按降序排序)然后根据键对它们进行排序。保留7个第一个元素,映射到它们的键(对应于单词)并收集到-webkit-text-fill-color
中,从而保持相遇顺序。
List
输出:
public static void main(String[] args) {
String sentence = "Hello alan i am here where are you and what are you doing hello are you there";
List<String> words = Arrays.asList(sentence.split(" "));
List<String> result =
words.stream()
.map(String::toLowerCase)
.collect(groupingBy(identity(), counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long> comparingByValue(reverseOrder()).thenComparing(Map.Entry.comparingByKey()))
.limit(7)
.map(Map.Entry::getKey)
.collect(toList());
System.out.println(result);
}
请注意,您在想要的输出中犯了一个错误:[are, you, hello, alan, am, and, doing]
实际上出现了3次,如"are"
所以它应该在之前
注意:此代码假定有很多静态导入,即:
"you"
答案 1 :(得分:4)
虽然@Tunaki解决方案很棒,但使用my StreamEx library很有意思,它可以解决单流管道中的问题(直到单终端操作才会执行实际操作被称为):
Map<String, Long> map = StreamEx.of(words)
.map(String::toLowerCase)
.sorted() // sort original words, so now repeating words are next to each other
.runLengths() // StreamEx feature: squash repeating words into Entry<String, Long>
.sorted(Entry.<String, Long> comparingByValue().reversed()
.thenComparing(Entry.comparingByKey()))
.limit(7) // Sort and limit
.toCustomMap(LinkedHashMap::new); // Single terminal operation: store to LinkedHashMap
或者只需要单词:
List<String> list =StreamEx.of(words)
.map(String::toLowerCase)
.sorted() // sort original words, so now repeating words are next to each other
.runLengths() // StreamEx feature: squash repeating words into Entry<String, Long>
.sorted(Entry.<String, Long> comparingByValue().reversed()
.thenComparing(Entry.comparingByKey()))
.limit(7) // Sort and limit
.keys() // Drop counts leaving only words
.toList(); // Single terminal operation: store to List
答案 2 :(得分:1)
我是一个简单的人,所以我先使用time
来计算每个单词。
然后为每个计数创建Map<String, Integer>
,并将其存储在TreeSet
中。从那里应该相当直截了当。
答案 3 :(得分:0)
两步解决方案:组/计数,然后按计数降序处理
List<String> words = Arrays.asList("Hello alan i am here where are you and what are you doing hello you there".split(" "));
Map<String, Long> collect = words.stream()
.map(String::toLowerCase) // convert to lower case
.collect( // group and count by name
Collectors.groupingBy(Function.identity(), Collectors.counting()));
collect.keySet().stream()
.sorted( // order by count descending, then by name
Comparator
.comparing(collect::get)
.reversed()
.thenComparing(Collator.getInstance()))
.map(k -> k + " (" + collect.get(k) + ")") // map to name and count string
.limit(7) // only first 7 entries
.forEach(System.out::println); // output