读取csv文件并在Lambda(Java8)中筛选特定列

读取csv文件并在Lambda(Java8)中筛选特定列,java,lambda,java-8,bufferedreader,filereader,Java,Lambda,Java 8,Bufferedreader,Filereader,假设我有一个文件,其中包含逗号分隔格式的数据,如下所示 TIMESTAMP,COUNTRYCODE,RESPONSETIME,FLAG 1544190995,US,500,Y 1723922044,GB,370,N 1711557214,US,750,Y 我的要求是,我希望读取此文件并根据列(时间戳和响应时间)过滤数据,并检查数据是否为数字 我尝试了以下方法,但没有成功。有人能帮我吗? BufferedReader br = new BufferedReader(new FileReader

假设我有一个文件,其中包含逗号分隔格式的数据,如下所示

TIMESTAMP,COUNTRYCODE,RESPONSETIME,FLAG

1544190995,US,500,Y
1723922044,GB,370,N
1711557214,US,750,Y
我的要求是,我希望读取此文件并根据列(时间戳和响应时间)过滤数据,并检查数据是否为数字

我尝试了以下方法,但没有成功。有人能帮我吗?

BufferedReader br = new BufferedReader(new FileReader(file));

rows = br.lines().map(line -> Arrays.asList(line.split(DELIMITER))).filter(a -> a.equals("TIMESTAMP")).collect(Collectors.toList());

目前,您正在做的就是:

  • 阅读给出以下内容的所有行:
    列表
  • 您将其拆分为
    字符串[]
    ,然后将其转换为
    列表
    (这是正确的),但您在一个映射中,因此映射的结果是
  • 您可以进行筛选,
    a
    是一个
    列表
    。您尝试比较
    列表
    字符串
    。 Bip Bip bop bop,问题
    就像@YCF_L所说的,在没有lambda的情况下尝试一下。

    当前,在
    映射
    操作之后,您有一个
    ,您试图将其与
    字符串
    进行比较,因此将永远不会产生预期的结果

    现在,解决方案;据我所知,如果
    时间戳
    响应时间
    是有效整数,那么您似乎希望保留整行

    一种方法是:

     List<String> rows = br.lines()
                .skip(1) // skip headers
                .map(s -> new AbstractMap.SimpleEntry<>(s,s.split(DILIMETER)))
                .filter(a -> isInteger(a.getValue()[0]) && isInteger(a.getValue()[2]))
                .map(AbstractMap.SimpleEntry::getKey)
                .collect(Collectors.toList());
    
    另一种解决方案是,如果要检索一个
    列表
    ,其中每个数组表示每行的单个数据,则可以执行以下操作:

    List<String[]> rows = br.lines()
                    .skip(1) // skip headers
                    .map(s -> s.split(DILIMETER))
                    .filter(a -> isInteger(a[0]) && isInteger(a[2]))
                    .collect(Collectors.toList());
    
    List rows=br.lines()
    .skip(1)//跳过标题
    .map(s->s.split(DILIMETER))
    .filter(a->isInteger(a[0])&&isInteger(a[2]))
    .collect(Collectors.toList());
    


    注意,如果只读文件包含不带标题的数据,则无需执行
    跳过
    操作。

    问题在于,您只会得到一个满是“TIMESTAMP”的列表,这是没有用的。 如果文件格式始终相同(即标题的顺序和数量),则可以跳过第一行,然后读取包含数据的每一行,并仅访问包含要验证的数据的列。最好使用for或while循环,这样您就可以提前终止

    boolean allNumericData = true;
    do{
       String[] row = br.nextLine().split(DELIMITER)
       if(!isNumeric(row[0])||!isNumeric(row[2])){
           allNumericData = false;
       }
    }while(allNumericData ||br.nextRow = null)
    
    如果标题可以不同 然后打开文件读取第一行以确定验证所需数据的索引,并使用找到的索引执行上述操作。
    这也是伪代码。您需要对下一行进行抓取和空值检查的验证和处理

    您也可以使用
    flatMap
    以及以后仅过滤包含数字的字符串:

    List<String> timeAndResponse = br.lines()
            .flatMap(s -> Arrays.stream(s.split(",")))
            .filter(s -> s.chars().allMatch(Character::isDigit))
            .collect(Collectors.toList());
    

    我希望这能有所帮助。

    你说它不起作用是什么意思?你有没有尝试在没有lambda的情况下实现它,因为我看到映射返回
    ArrayList
    ,然后你使用
    .filter(a->a.equals(“TIMESTAMP”)
    这不是逻辑
    ArrayList
    不是
    字符串
    没有?我的意思是,它没有给我预期的结果。预期结果:如果两个字段都是数字(TIMESTAMP和RESPONSETIME)->“false”->其中任何一个字段都是非数字(TIMESTAMP和RESPONSETIME)),它应该返回布尔值->'true'->谢谢。我们不能用lamda来实现吗?不,您可以,请您向我们显示
    br.lines().forEach(System.out::println)
    映射操作的结果是
    Stream
    而不是
    List
    。您是对的!要意识到这一点,但你对我来说太快了;)
    List<String> timeAndResponse = br.lines()
            .flatMap(s -> Arrays.stream(s.split(",")))
            .filter(s -> s.chars().allMatch(Character::isDigit))
            .collect(Collectors.toList());
    
    [1544190995, 500, 1723922044, 370, 1711557214, 750]