java - Java Streams - 将两个字符串行分别映射到一个对象
问题描述
假设我们有一个包含(product name, price)
对的文本文件。每对在文本文件中占据两行,其中第一行对应产品名称,第二行对应该产品的价格。我们可以假设文本文件的格式正确(并且行数是偶数)
例子:
Ice Cream
$3.99
Chocolate
$5.00
Nice Shoes
$84.95
...
现在我有一个简单的类来表示这样的对:
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将每两行映射到一个 type 对象Product
。
如何将两条线分别分组,然后将它们映射到一个Product
?如果有一种简单的方法,它是否仍然适用于并行流?
解决方案
您可以制作自己的Collector
临时存储前一个元素/字符串。当前元素以 a 开头时$
,产品名称存储在 中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", "$3.99",
"Chocolate", "$5.00",
"Nice Shoes", "$84.95"
};
List<Product> products = Stream.of(lines)
.sequential()
.collect(ProductCollector.collector());
请注意,您的价格不是整数,这就是我使用双精度来正确表示它们的原因。
推荐阅读
- typo3 - 如何在 TYPO3 中获取文件引用对象的 uid?
- java - 如何使用 WebScript 上传文件的新版本?
- javascript - Node JS async/await 与多个 fs.writeFile 使用 through2 (Gulp/Vinyl)
- javascript - 返回从 select2 和 fiter 排序的 json
- java - 需要一种更好的方法将测试代码排除在生产代码之外 - slf4jtesting
- javascript - JavaScript 模块模式:用户可实现的功能
- sql - SQL 从每组中取 1 MAX
- javascript - 单击时选择列表中的第一项
- java - 尝试将 null 插入摄取附件字段时,ElasticSearch 返回错误
- javascript - Javascript比较看起来相似的unicode字符