Java 8 Streams:计算文本数据列表(List<String> list2)中元素(List<String> list1)的出现次数

use*_*969 5 java sorting java-8 java-stream

输入 :

List<String> elements= new ArrayList<>();
        elements.add("Oranges");
        elements.add("Figs");
        elements.add("Mangoes");
        elements.add("Apple");

List<String> listofComments = new ArrayList<>();
        listofComments.add("Apples are better than Oranges");
        listofComments.add("I love Mangoes and Oranges");
        listofComments.add("I don't know like Figs. Mangoes are my favorites");
        listofComments.add("I love Mangoes and Apples");
Run Code Online (Sandbox Code Playgroud)

输出:[芒果、苹果、橙子、无花果] -> 输出必须按元素出现次数的降序排列。如果元素出现等于 no。那么它们必须按字母顺序排列。

我是 Java 8 的新手,遇到了这个问题。我尝试部分解决它;我无法排序。谁能帮助我编写更好的代码?

我的一段代码:

Function<String, Map<String, Long>> function = f -> {
            Long count = listofComments.stream()
                    .filter(e -> e.toLowerCase().contains(f.toLowerCase())).count();
            Map<String, Long> map = new HashMap<>(); //creates map for every element. Is it right?
            map.put(f, count);
            return map;
        };

elements.stream().sorted().map(function).forEach(e-> System.out.print(e));
Run Code Online (Sandbox Code Playgroud)

输出:{苹果=2}{无花果=1}{芒果=3}{橙子=2}

Hol*_*ger 3

在现实生活中,您必须考虑到,当数量增长时,将任意数量的匹配操作应用于任意数量的评论可能会变得非常昂贵,因此\xe2\x80\x99s值得做一些准备:

\n\n
Map<String,Predicate<String>> filters = elements.stream()\n    .sorted(String.CASE_INSENSITIVE_ORDER)\n    .map(s -> Pattern.compile(s, Pattern.LITERAL|Pattern.CASE_INSENSITIVE))\n    .collect(Collectors.toMap(Pattern::pattern, Pattern::asPredicate,\n        (a,b) -> { throw new AssertionError("duplicates"); }, LinkedHashMap::new));\n
Run Code Online (Sandbox Code Playgroud)\n\n

Predicate即使不进行正则表达式匹配,该类也非常有价值。LITERAL和标志的组合CASE_INSENSITIVE可以使用预期语义进行搜索,而无需将整个字符串转换为小写(顺便说一句,这不足以满足所有可能的情况)。对于这种匹配,准备工作将包括为Boyer\xe2\x80\x93Moore 算法构建必要的数据结构,以便在内部进行更有效的搜索。

\n\n

这张地图可以重复使用。

\n\n

对于您的特定任务,使用它的一种方法是

\n\n
filters.entrySet().stream()\n    .map(e -> Map.entry(e.getKey(), listofComments.stream().filter(e.getValue()).count()))\n    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))\n    .forEachOrdered(e -> System.out.printf("%-7s%3d%n", e.getKey(), e.getValue()));\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将打印您的示例数据:

\n\n
Mangoes  3\nApple    2\nOranges  2\nFigs     1\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,filters映射已经按字母顺序排序,并且对于具有定义的遇到顺序的流来说,sorted第二个流操作是稳定的,因此只需按出现次数排序,具有相等元素的条目将保持其相对顺序,即字母顺序从源地图。

\n\n

Map.entry(\xe2\x80\xa6)需要 Java\xc2\xa09 或更高版本。对于 Java\xc2\xa08,\xe2\x80\x99d 必须使用类似
\n的内容new AbstractMap.SimpleEntry(\xe2\x80\xa6)

\n