将所有类别的所有列表拆分为子类别? (仅限 Java)

Split all list of all categories into subcategories? (with Java only)

我们有一个实体 class 和所有类别的列表:

class Category {
  Long id, parentId;
}
...
List<Category> categoryList = <...>;

如何转换为这样的 DTO 列表:

class CategoryDTO {
  Long id; 
  List<CategoryDTO> subcategories;
}

如果没有一对一的实体关系,如何做到这一点?

创建一个 Map<Long, CategoryDTO> 并从 categoryList 填充它,将 id 映射到从 Category 对象创建的 CategoryDTO

然后再次遍历 categoryList,在映射中查找 idparentId,并根据需要添加到 subcategories 列表中。

例如像这样:

Map<Long, CategoryDTO> categoryDTOs = new LinkedHashMap<>();
for (Category category : categoryList) {
    categoryDTOs.put(category.getId(), new CategoryDTO(category.getId()));
}
for (Category category : categoryList) {
    if (category.getParentId() != null) {
        categoryDTOs.get(category.getParentId())
                    .addSubcategory(categoryDTOs.get(category.getId()));
    }
}
public class CategoryConverterImpl implements CategoryConverter {
    private CategoryDTO convertEntity(Category s) {
        Long id = s.getId();
        return new CategoryDTO()
                .setId(id)
                .setSubcategories(
                        convertCollection(
                                categoryCollection.stream()
                                        .filter(c -> Objects.equals(c.getParentCategoryId(), id))
                                        .collect(Collectors.toList())
                        )
                );
    }

    private List<CategoryDTO> convertCollection(Collection<Category> categoryCollection) {
        return categoryCollection.stream()
                .map(this::convertEntity)
                .collect(Collectors.toList());
    }

    private Collection<Category> categoryCollection;

    @Override
    public List<CategoryDTO> convert(Collection<Category> categoryCollection) {
        this.categoryCollection = categoryCollection;
        return categoryCollection.stream()
                .filter(c -> c.getParentCategoryId() == null)
                .map(this::convertEntity)
                .collect(Collectors.toList());
    }
}