Cug*_*uga 6 java lambda java-8 java-stream collectors
我一直在努力阅读javadocs,以确定如何使用lambdas优雅地将一种类型的行列表组合成另一种类型的分组列表.
我已经弄清楚如何使用Collectors.groupingBy语法来获取数据,Map<String, List<String>>但是因为结果将用于各种后来的函数调用...我理想地希望将这些缩减为包含以下内容的对象列表新的映射.
这是我的数据类型,RowData是源...我想将数据合并到一个列表中CodesToBrands:
class RowData {
private String id;
private String name;
public RowData() {
}
public RowData(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class CodeToBrands {
private String code;
private List<String> brands = new ArrayList<>();
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<String> getBrands() {
return brands;
}
public void addBrands(List<String> brands) {
this.brands.addAll(brands);
}
public void addBrand(String brand) {
this.brands.add(brand);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我正在编写的测试,试图弄明白......
@Test
public void testMappingRows() {
List<RowData> rows = new ArrayList<>();
rows.add(new RowData("A", "Foo"));
rows.add(new RowData("B", "Foo"));
rows.add(new RowData("A", "Bar"));
rows.add(new RowData("B", "Zoo"));
rows.add(new RowData("C", "Elf"));
// Groups a list of elements to a Map<String, List<String>>
System.out.println("\nMapping the codes to a list of brands");
Map<String, List<String>> result = rows.stream()
.collect(Collectors.groupingBy(RowData::getId, Collectors.mapping(RowData::getName, Collectors.toList())));
// Show results are grouped nicely
result.entrySet().forEach((entry) -> {
System.out.println("Key: " + entry.getKey());
entry.getValue().forEach((value) -> System.out.println("..Value: " + value));
});
/**Prints:
* Mapping the codes to a list of brands
Key: A
..Value: Foo
..Value: Bar
Key: B
..Value: Foo
..Value: Zoo
Key: C
..Value: Elf*/
// How to get these as a List<CodeToBrand> objects where each CodeToBrand objects to avoid working with a Map<String, List<String>>?
List<CodeToBrands> resultsAsNewType;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供任何帮助,试图在一个更容易使用的数据类型中获得相同的整体结果?
提前致谢
您可以使用Collectors.toMap以下命令一次完成:
Collection<CodeToBrands> values = rows.stream()
.collect(Collectors.toMap(
RowData::getId,
rowData -> {
CodeToBrands codeToBrands = new CodeToBrands();
codeToBrands.setCode(rowData.getId());
codeToBrands.addBrand(row.getName());
return codeToBrands;
},
(left, right) -> {
left.addBrands(right.getBrands());
return left;
}))
.values();
Run Code Online (Sandbox Code Playgroud)
然后,如果您需要List而不是a Collection,只需执行以下操作:
List<CodeToBrands> result = new ArrayList<>(values);
Run Code Online (Sandbox Code Playgroud)
如果您在类中有特定的构造函数和合并方法,则可以简化上面的代码CodeToBrands:
public CodeToBrands(String code, String brand) {
this.code = code;
this.brands.add(brand);
}
public CodeToBrands merge(CodeToBrands another) {
this.brands.addAll(another.getBrands());
return this;
}
Run Code Online (Sandbox Code Playgroud)
然后,只需:
Collection<CodeToBrands> values = rows.stream()
.collect(Collectors.toMap(
RowData::getId,
rowData -> new CodeToBrands(rowData.getId(), rowData.getName()),
CodeToBrands::merge))
.values();
Run Code Online (Sandbox Code Playgroud)