嗨,我有一个对象数组,其中类别和子类别详细信息位于同一对象中。就像
public class MyObject {
String categoryCode;
String categeoryCodeDescription;
String subCategoryCode;
String subCategoryCodeDescription;
public MyObject(String categoryCode, String categeoryCodeDescription, String subCategoryCode, String subCategoryCodeDescription) {
this.categoryCode = categoryCode;
this.categeoryCodeDescription = categeoryCodeDescription;
this.subCategoryCode = subCategoryCode;
this.subCategoryCodeDescription = subCategoryCodeDescription;
}
}
List<MyObject> collection = new ArrayList<MyObject>;
collection.add(new My Object("A1", "descA1", "A1A", "descA1A"));
collection.add(new My Object("A1", "descA1", "A1B", "descA1B"));
collection.add(new My Object("A1", "descA1", "A1C", "descA1C"));
collection.add(new My Object("A2", "descA1", "A2A", "descA2A"));
collection.add(new My Object("A2", "descA1", "A2B", "descA2B"));
可以按类别代码分组,但同时映射到包含描述的对象。因此,如果我有两个类。.
public class Category {
String categoryCode;
String categoryDesc;
public Category (String categoryCode, String categoryDesc) {
this.categoryCode = categoryCode;
this.categoryDesc = categoryDesc;
}
}
public class SubCategory {
String subCategoryCode;
String subCategoryDesc;
public SubCategory (String subCategoryCode, String subCategoryDesc) {
this.subCategoryCode = subCategoryCode;
this.subCategoryDesc = subCategoryDesc;
}
}
..并且我要将集合列表分组为Map<Category,List<SubCategory>>
。我可以对类别代码进行分组,但是看不到如何创建新的类别实例作为映射键。在一个衬套中可能无法做到这一点。
Map<String, List<MyObject>> map = collection.stream().collect(Collectors.groupingBy(MyObject::getCategoryCode));
答案 0 :(得分:4)
如果将mapping
收集器链接到groupingBy
,就可以完成。
您使用mapping()
将MyObject
实例转换为SubCategory
实例。
Map<Category,List<SubCategory>> map =
collection.stream().collect(Collectors.groupingBy(mo -> new Category(mo.getCategoryCode(),mo.getCategoryDesc()),
Collectors.mapping(mo->new SubCategory(mo.getSubCategoryCode(),mo.getSubCategoryDesc()),
Collectors.toList())));
请注意,Category
必须覆盖equals
和hashCode
才能使此分组正常工作。
答案 1 :(得分:4)
您可以通过使用合并功能的toMap
收集器来完成此操作:
Map<Category, List<SubCategory>> result = collection.stream()
.collect(toMap(e -> new Category(e.getCategoryCode(), e.getCategeoryCodeDescription()),
v -> new ArrayList<>(singletonList(new SubCategory(v.getSubCategoryCode(), v.getSubCategoryCodeDescription()))),
(l, r) -> { l.addAll(r); return l; }));
这假定您Category类已经重写了equals和hashcode方法,如下所示:
class Category {
...
... // properties + getters + constructors etc..
...
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Category category = (Category) o;
return Objects.equals(categoryCode, category.categoryCode);
}
@Override
public int hashCode() {
return Objects.hash(categoryCode);
}
}
要获得更好的可读性,您可以将keyMapper
,valueMapper
和merge
函数提取为以下不同函数:
private static List<SubCategory> valueMapper(MyObject v) {
return new ArrayList<>(singletonList(new SubCategory(v.getSubCategoryCode(), v.getSubCategoryCodeDescription())));
}
private static List<SubCategory> merge(List<SubCategory> l, List<SubCategory> r) {
l.addAll(r);
return l;
}
private static Category keyMapper(MyObject e) {
return new Category(e.getCategoryCode(), e.getCategeoryCodeDescription());
}
那么您可以做:
Map<Category, List<SubCategory>> result = collection.stream()
.collect(toMap(Main::keyMapper,
Main::valueMapper,
Main::merge));
Main
是包含keyMapper
,valueMapper
和merge
方法的类。