当前位置: 首页 > 知识库问答 >
问题:

使用stream和lambda表达式从文件中提取数字

商华藏
2023-03-14

我试图使用Java8流和lambda表达式仅从我的list list 中提取数字。首先,我要做的是将字符串从文件加载到列表。之后,我过滤stream以获得包含“PL”的字符串。

Jan Kowalski PL 35000
Jiri Prohazka CZ 28000
Anna Malinowska PL 52000
Jozef Bak PL 49999
Helmut Schnittke DE 45000
Kleofas Oginski PL 45000
John Bull US 74000
Lukasz Zolw PL 9400
Franz Beckenbauer DE 83000
Frantisek Kupka CZ 32000
List<String> list = new ArrayList<>();
try (Stream<String> stream = Files.lines(Paths.get("file"),Charset.defaultCharset())) {
    list = stream
        .filter(line -> line.contains("PL"))
        .peek(System.out::println)
        .collect(Collectors.toList());
}

我认为现在最好的方法是删除字符串中的所有字母,只保留小数,但我有问题应该怎么做。最终的结果应该让我将list的元素解析为integer,对它们进行排序,并得到前三个元素的和。我已经做过了,但我肯定有更好的方法来做(例如,只用一个列表)

List<Integer> iList = new ArrayList<Integer>();
        list.forEach(s->
        {
            s = s.replaceAll("\\D+","");
            iList.add(Integer.parseInt(s));
        });
        Collections.sort(iList);
        Collections.reverse(iList); 
        int sum = 0;
        for(int i=0;i<3;i++){
            sum=sum+iList.get(i); 
        }

有什么想法如何做到这一点而不使用任何额外的列表?

共有1个答案

孔嘉茂
2023-03-14

您可以在单个流管道中进行操作。要提取该数字,可以使用pattern并为该数字创建捕获组。在这种情况下,模式将是“(\\d+)”

通过在pattern.matcher(input)的帮助下创建匹配器,使用matcher.find()再次筛选实际包含数字的行,并使用matcher.group(group)提取捕获的数字来实现。在本例中,数字是第一个捕获的元素,因此它在组1中。

此流通过Stream.map(映射器)转换为Stream :这里的映射器是返回从每行解析的integer值的函数。最后,要对三个最大的元素求和,流按相反的顺序排序(sorted(comparator),其中比较器是reverseorder()),仅限于前3个元素(limit(3)),然后对这些元素求和(sum(),方法是首先使用Stream.maptointStream Stream 转换为 intstream)。

public static void main(String[] args) throws IOException {
    Pattern pattern = Pattern.compile("(\\d+)");
    try (Stream<String> stream = Files.lines(Paths.get("file"))) {
        int sum = 
            stream.filter(line -> line.contains("PL"))
                  .map(pattern::matcher)
                  .filter(Matcher::find)
                  .map(m -> Integer.valueOf(m.group(1)))
                  .sorted(Comparator.reverseOrder())
                  .limit(3)
                  .mapToInt(Integer::intValue)
                  .sum();
        System.out.println(sum);
    }
}

对于问题中的示例,输出为146999。

如果您确信在文件中,“PL”标识符将位于要提取的数字之前,您甚至可以删除第一个筛选操作,并使用模式“.*PL.*?(\\d+)”:此模式将匹配包含“PL”的行并捕获相应的数字。

 类似资料:
  • 本文向大家介绍Java8中Lambda表达式使用和Stream API详解,包括了Java8中Lambda表达式使用和Stream API详解的使用技巧和注意事项,需要的朋友参考一下 前言 Java8 的新特性:Lambda表达式、强大的 Stream API、全新时间日期 API、ConcurrentHashMap、MetaSpace。总得来说,Java8 的新特性使 Java 的运行速度更快、

  • 问题内容: 我试图在 jrxml 文件中使用lambda表达式来获取我的字段的值。 我导入了适当的类,但这给了我错误 p无法解析为变量。 如何在 JasperReports 模板中使用Lambda表达式? 例外: 问题答案: 如果您使用的是Eclipse JDT编译器,请首先确保您具有一个相当新的版本。 例如,您可以从Maven获得4.5.1 ,然后将以下属性添加到jasperreports.pr

  • 在我的项目中,我使用Guava谓词和函数来使用和筛选和转换一些集合。 在这次迁移中,我需要将guava代码更改为Java8更改。所以,我所做的改变是这样的: 到... 由于,使用方法引用的方法还允许我调试转换过程: 多亏了answer,我注意到我的Eclipse没有显示它应该显示的内容,而peek()的使用有助于显示结果。

  • 在我们的项目中,我们将迁移到Java8,并测试它的新特性。 在我的项目中,我使用Guava谓词和函数,使用和过滤和转换一些集合。 在这次迁移中,我需要更改例如guava代码到Java8的更改。所以,我正在做的改变是: 到... 使用guava调试代码非常符合要求,因为我可以调试每个转换过程,但我关心的是如何调试,例如。 由于,使用方法引用的方法还允许我调试转换过程: 由于回答,我注意到我的Ecli

  • 我有以下JSON文件。文件中的点是以下内容: 使用RegEx,我想提取CCG代码属性,并将其添加回,以便上面的内容变成: 我已经尝试了各种方法,但我就是无法让它工作。我正在使用Sublime文本。 上面选择了代码,但不确定如何让它创建属性。

  • 问题内容: 我想从一般的HTML页面中提取所有文本(是否显示)。 我想 删除 任何HTML标记 任何JavaScript 任何CSS样式 是否有一个正则表达式(一个或多个)可以实现? 问题答案: 您不能真正用正则表达式解析HTML。太复杂了。RE根本无法正确处理部分。此外,某些常见的HTML之类的东西将在浏览器中作为适当的文本工作,但可能会使天真的RE感到困惑。 有了合适的HTML解析器,您会更快