Java Streams - 将两个字符串行分别映射到一个对象

Java Streams - Map two string lines each to one object

假设我们有一个包含 (product name, price) 对的文本文件。每对在文本文件中占据两行,其中第一行对应产品名称,第二行对应该产品的价格。我们可以假设文本文件的格式正确(并且行数相等)

示例:

Ice Cream
.99
Chocolate
.00
Nice Shoes
.95
...

现在我有一个简单的 class 表示这样的对:

public class Product {
    private final String name;
    private final int price;

    public Product(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return this.name;
    }

    public int getPrice() {
        return this.price;
    }
}

我们读取了包含对的文件,现在有一个包含所有单独行的字符串数组。我需要使用 Streams 将每两行映射到一个 Product.

类型的对象

如何将两行分别分组,然后将它们映射到 Product?如果有一个简单的方法,它是否仍然适用于并行流?

如果你有数组中的项目,你可以使用 vanilla java 和 intStream 并过滤偶数值,然后在下一个映射中你可以使用索引和索引+1。也许看看here

您可以制作自己的 Collector,临时存储之前的 element/string。当当前元素以 $ 开头时,产品名称存储在 prev 中。现在您可以将价格转换为双精度并创建对象。

private class ProductCollector {

    private final List<Product> list = new ArrayList<>();

    private String prev;

    public void accept(String str) {
        if (prev != null && str.startsWith("$")) {
            double price = Double.parseDouble(str.substring(1));
            list.add(new Product(prev, price));
        }
        prev = str;
    }

    public List<Product> finish() {
        return list;
    }

    public static Collector<String, ?, List<Product>> collector() {
        return Collector.of(ProductCollector::new, ProductCollector::accept, (a, b) -> a, ProductCollector::finish);
    }
}

由于需要依赖序列(价格行在名称行之后),流无法并行处理。以下是使用自定义收集器的方法:

String[] lines = new String[]{
        "Ice Cream", ".99",
        "Chocolate", ".00",
        "Nice Shoes", ".95"
};

List<Product> products = Stream.of(lines)
        .sequential()
        .collect(ProductCollector.collector());

请注意,您的价格不是整数,这就是为什么我使用双精度来正确表示它们的原因。