读取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]