Map 8函数的多个输入参数

时间:2018-04-21 22:40:43

标签: java data-structures lambda java-stream

  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”

3 个答案:

答案 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)