File inputF = new File("C:\\sample.csv"); //Line 1
InputStream inputFS = new FileInputStream(inputF); //Line2
BufferedReader br = new BufferedReader(new InputStreamReader(inputFS)); // Line3
inputList = br.lines().skip(1).map(createObject).collect(Collectors.toList()); // Line 4 Function createobject below
在上面的第四行中,我将从CSV文件中读取的行列表传递给下面的函数createObject
。我还有另一个csv文件,其中包含项目列表。假设我在上面的函数中也读过第二个文件..现在我怎样才能将第二个文件中的行列表与第一个文件一起传递给createObject
函数。我也想传递第二个文件,因为我想检查第一个文件中的项目是否存在于第二个文件中
public static Function<String, YouJavaItem> createObject= (line) -> {
List<String> firstFile= Arrays.asList(line.split(","));
示例:我想检查firstFile.get(2)是否在file2 {“lmn”,“ukl”,“xyz”,“abc”}
中的项目列表中显示“abc”答案 0 :(得分:1)
您需要声明createObject
一个BiFunction<String,List<String>,YourJavaObject>
,以便它可以接受当前行和您从第二个文件中读取的List<String>
。
在阅读第一个文件之前,您可以将第二个文件读入List
,因为您需要为第一个文件的每个元素提供其内容:
List<String> secondFileContents = Files.readAllLines(Paths.get("C:\\secondFile"));
现在您可以使用它传递给createObject
- 这需要一个参数。
Path firstFile = Paths.get("C:\\sample.csv");
List<YourJavaItem> result = Files.lines(firstFile).skip(1)
.map(line -> YourClass.createObject(line, secondFileContents))
.collect(Collectors.toList());
至于您的示例,createObject
方法可能如下所示:
BiFunction<String,List<String>,YourJavaItem> createObject =
(line, sfc) -> {
if ("abc".equals(sfc.get(2))) {
System.out.println("abc found!");
}
return new YourJavaItem(line);
}
}
如果您只想创建一个List<String>
不包含第二个文件中的项目,您只需过滤:
List<String> result = Files.lines(firstFile).skip(1)
.flatMap(line -> Arrays.asList(line).stream()
.filter(item -> !secondfileContents.contains(item)))
.collect(Collectors.toList());
使用就地lambda
如果在读取行的函数中将createObject
定义为lambda,您仍然可以使用Function<String,YourJavaObject>
并引用从第二个文件中读取的本地定义的List<String>
。
List<String> secondFileContents = Files.readAllLines(Paths.get("C:\\secondFile"));
Function<String,YourJavaObject> mapper = line -> {
if ("abc".equals(secondFileContents.get(2))) {
System.out.println("abc found!");
}
return new YourJavaItem(line);
}
List<YourJavaItem> result = Files.lines(firstFile).skip(1)
.map(mapper)
.collect(Collectors.toList());
答案 1 :(得分:0)
如果第二个文件的大小不是太大,那么将整个内容存储在内存中是可以负担得起的,那么最佳解决方案显然是加载并存储在HashSet
中。这为检查第一个文件的项目带来了最低的成本。
Set<String> file2Items;
try (Stream<String> lines = Files.lines(Paths.get(file2Name))) {
file2Items = Files.lines(Paths.get(file2Name)).collect(Collectors.toSet());
} catch (IOException e) {
throw new IllegalStateException("Error reading " + file2Name);
}
try (Stream<String> lines = Files.lines(Paths.get(file1Name))) {
inputList = lines.filter(x -> !file2Items.contains(x)).map(createObject).collect(Collectors.toList());
} catch (IOException e) {
// any exception handling you prefer.
}
如果文件大小很重要,逐行读取文件有助于节省多达50%的所需内存,因为您不需要将整个文件作为一组行加载然后转换在行符合GC
之前成功进入对象答案 2 :(得分:-1)
现在我如何将第二个文件中的行列表与第一个文件一起传递给createObject函数。我想传递第二个文件,因为我想检查第一个文件中的项是否存在于第二个文件中
如果要检查第一个文件中的项目是否存在于第二个文件中,则不需要合并这两个文件,只需映射第二个文件中的项目以及要在第一个文件中检查的项目createObject
,然后使用Collection.contains
方法。
更具体地说,您要检查file2中的项目列表中是否存在firstFile.get(2):
static class YourJavaItem {
YourJavaItem(String word) {
}
}
public static Function<String, Stream<YourJavaItem>> createObject = (line) -> {
return Arrays.stream(line.split(",")).map(YourJavaItem::new);
};
public static void main(String[] args) throws FileNotFoundException {
File inputF1 = new File("C:\\sample.csv");
File inputF2 = new File("C:\\sample.csv");
InputStream inputFS1 = new FileInputStream(inputF1);
InputStream inputFS2 = new FileInputStream(inputF2);
BufferedReader br1 = new BufferedReader(new InputStreamReader(inputFS1));
BufferedReader br2 = new BufferedReader(new InputStreamReader(inputFS2));
Set<YourJavaItem> set = br2.lines().flatMap(createObject).collect(Collectors.toSet());
YourJavaItem keyword = br1.lines().flatMap(createObject).collect(Collectors.toList()).get(2);
boolean whatYouWant = set.contains(keyword);
// Don't forget to close file resources
}
但如果您坚持合并这两个文件,则可以使用Stream.concat
:
Stream.concat(br1.lines(), br2.lines()).flatMap(createObject)