【问题标题】:java 8 stream multiple filtersjava 8流多个过滤器
【发布时间】:2018-12-17 17:57:22
【问题描述】:

我是 Java 8 的新手,正在尝试对 Streams 的要求。我有一个包含数千条记录的 csv 文件,我的 csv 格式是

DepId、GrpId、EmpId、DepLocation、NoofEmployees、EmpType === D100,CB,244340,USA,1000,合同 D101,CB,543126,USA,1900,永久 D101,CB,356147,USA,1800,合同 D100,DB,244896,HK,500,SemiContract D100,DB,543378,HK,100,永久

我的要求是用两个条件过滤记录 a) EmpId 以“244”开头或 EmpId 以“543”开头 b) EmpType 是“Contract”和“Permanent”

我在下面尝试过

 try (Stream<String> stream = Files.lines(Paths.get(fileAbsolutePath))) {
    list = stream                
        .filter(line -> line.contains("244") || line.contains("543"))
        .collect(Collectors.toList());
     }

它正在根据 244 和 543 过滤员工,但我担心的是,因为我使用的是 contains,它可能还会获取其他数据,即它不仅会从 EmpId 列中获取数据,而且还会从其他列中获取数据(其他列也可能有以这些数字开头的数据)

类似地合并 EmpType,因为我正在逐行阅读,我无法强制 EmpType 应该在“Permanent”和“Contract”中

我是否缺少任何高级选项?

【问题讨论】:

  • 使用正则表达式是最简洁的方法。否则,将每个String(代表每一行)用,打断,然后取索引2的子串进行比较。

标签: java filter java-stream


【解决方案1】:

你可以这样做,

Pattern comma = Pattern.compile(",");
Pattern empNum = Pattern.compile("(244|543)\\d+");
Pattern empType = Pattern.compile("(Contract|Permanent)");
try (Stream<String> stream = Files.lines(Paths.get("C:\\data\\sample.txt"))) {
    List<String> result = stream.skip(2).map(l -> comma.split(l))
            .filter(s -> empNum.matcher(s[2]).matches())
            .filter(s -> empType.matcher(s[5]).matches())
            .map(s -> Arrays.stream(s).collect(Collectors.joining(",")))
            .collect(Collectors.toList());
    System.out.println(result);
} catch (IOException e) {
    e.printStackTrace();
}

首先读取文件并跳过 2 个标题行。然后使用, 字符拆分它。使用EmpIdEmpType 将其过滤掉。接下来,再次将标记合并回来形成行,最后将每一行收集成一个List

【讨论】:

  • 完美.. 谢谢:)
【解决方案2】:

优雅的方式是正则表达式,我现在将跳过它。使用 Stream API 的不太优雅的方式如下:

list = stream.filter(line -> {
    String empId = line.split(",")[2];
    return empId.startsWith("244") || empId.startsWith("543");
}.collect(Collectors.toList());

使用 Stream API(由 shmosel 指出)的更短的方法是使用迷你正则表达式。

list = stream.filter(line -> line.split(",")[2].matches("(244|543).*")
             .collect(Collectors.toList());

【讨论】:

  • line -&gt; line.split(",")[2].matches("(244|543).*")
  • @shmosel 或line -&gt; line.matches("([^,]*,){2}(244|543)(,.*)?")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
相关资源
最近更新 更多