如何使用java流来查找共享一个键的所有值的平均值?

uujelgoq  于 2021-06-30  发布在  Java
关注(0)|答案(4)|浏览(253)

我在java中尝试平均Map的值时遇到了很多麻烦。我的方法接收一个文本文件并查看每个单词的平均长度(不区分大小写)以某个字母开头,然后遍历文本文件中的所有单词。
例如,假设我有一个包含以下内容的文本文件:

"Apple arrow are very common Because bees behave Cant you come home"

我的方法当前返回:

{A=5, a=8, B=7, b=10, c=10, C=5, v=4, h=4, y=3}

因为它会查看字母并找到单词的平均长度,但它仍然区分大小写。
它应该返回:

{A=5, a=8, B=7, b=10, c=10, C=5, v=4, h=4, y=3}

{a=4.3, b=5.5, c=5.0, v=4.0, h=4.0, y=3}

这就是我目前所拥有的。

public static Map<String, Integer> findAverageLength(String filename) {

     Map<String, Integer> wordcount = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

        try 
        {
            Scanner in = new Scanner(new File(filename));
            List<String> wordList = new ArrayList<>();
            while (in.hasNext()) 
            {
                wordList.add(in.next());
            }

            wordcount = wordList.stream().collect(Collectors.toConcurrentMap(w->w.substring(0,1), w -> w.length(), Integer::sum));
            System.out.println(wordcount);

        }

        catch (IOException e)
        {
            System.out.println("File: " + filename + " not found");
        }

  return wordcount; 
}
72qzrwbm

72qzrwbm1#

你已经定义了一个不区分大小写的Map,但是你还没有使用它。尝试 Collectors.toMap(w->w.substring(0,1), w -> w.length(), Integer::sum, () -> new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER)) ,或者只是 Collectors.toMap(w->w.toUpperCase().substring(0,1), w -> w.length(), Integer::sum)

kg7wmglp

kg7wmglp2#

你就快到了。
你可以试试下面的方法。
我们按单词的第一个字符分组,转换成小写。这让我们收集到一个 Map<Character, …> ,其中键是每个单词的第一个字母。一个典型的Map条目看起来像

a = [ Apple, arrow, are ]

然后,使用 averagingDouble 方法。一个典型的Map条目看起来像

a = 4.33333333

代码如下:

// groupingBy and averagingDouble are static imports from
// java.util.stream.Collectors
Map<Character, Double> map = Arrays.stream(str.split(" "))
    .collect(groupingBy(word -> Character.toLowerCase(word.charAt(0)),
        averagingDouble(String::length)));

请注意,为简洁起见,我省略了其他内容,如 null 支票、空字符串和 Locale s。
还要注意的是,响应oliviergr的评论,这个代码得到了很大的改进é下面是戈尔和霍尔格。

mitkmikd

mitkmikd3#

您可以尝试以下操作:

String str = "Apple arrow are very common Because bees behave Cant you come home";
Map<String, Double> map = Arrays.stream(str.split(" "))
            .collect(Collectors.groupingBy(s -> String.valueOf(Character.toLowerCase(s.charAt(0))),
                    Collectors.averagingDouble(String::length)));

这个 split 方法将使用分隔符“”将字符串拆分为字符串数组。然后,您要根据字符串长度的平均值进行分组。因此,使用 Collectors.groupingBy 方法和下游参数 Collectors.averagingDouble(String::length) . 最后,根据您描述的约束条件,我们需要按字符串中第一个字符的小写(或大写)分组(即。, Character.toLowerCase(s.charAt(0))) ).
然后打印Map:

map.entrySet().forEach(System.out::println);

如果不需要保留Map结构,可以一次性完成:

Arrays.stream(str.split(" "))
      .collect(Collectors.groupingBy(s -> String.valueOf(Character.toLowerCase(s.charAt(0))), Collectors.averagingDouble(String::length)))
      .entrySet().forEach(System.out::println);
6rvt4ljy

6rvt4ljy4#

只需转换第一个字母,即使用 substring ,同样的情况。上还是下,没关系。

w.substring(0,1).toLowercase()

相关问题