简体   繁体   中英

How dep I can collect atributes values in a List of List with Lambda?

I have a Object with this structure:

public class CategoryDTO {

    @JsonProperty("id")
    private Long id;

    @JsonProperty("parentId")
    private Long parentId;

    @JsonProperty("name")
    private String nameCategory;

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private ComissaoPadraoEntity comission;

    @JsonProperty("categories")
    private List<CategoriaDTO> subcategories;

I make this method:

public Map<Long, List<Long>> mapATreeOfCategories(List<CategoryDTO> categories) {
        Map<Long, List<Long>> treeCategories = categoires.stream()
                .collect(Collectors.toMap(c -> c.getId(),
                        v -> v.getCategories().stream()
                                .map(e -> e.getId()).collect(Collectors.toList())));
        return treeCategories;

I have two problems here, first Te returns is this:

"1813": [1827,1830,1839,1834,1706,1822,2239,1835,2400,3290,3355,3319],...

OBS: They only cat de firs level as a key, and the second as values. It even considerate a third level.

if you look at the below structure i need the returns comes this way:

"1813":[1813]

"1827":[1827,1813]

"1830":[1830,1827,1813]

"1831":[1831,1830,1827,1813]



<!--Payload-->
      {
          "categories": [
            {
              "id": "1813",
              "parentId": null,
              "name": "Malas e Mochilas",
              "items": 12,
              "categories": [
                {
                  "id": "1827",
                  "parentId": "1813",
                  "name": "Conjuntos de Malas",
                  "items": 0,
                  "categories": [

                  ],
                  "attributes": null
                },
                {
                  "id": "1830",
                  "parentId": "1813",
                  "name": "Mochilas",
                  "items": 4,
                  "categories": [
                    {
                      "id": "1831",
                      "parentId": "1830",
                      "name": "Mochila Esportiva",
                      "items": 0,
                      "categories": [

                      ],

and the second one, I know this object only have three levels, but in the future if comes one more level i want to prevent this.

I want to know if there is a way to do this method with lambda, how dep one search with lambda can go. Or the only way is with the basic for each structure ?

Thanks for any help.

private void associarCategorias(List<CategoriaDTO> categorias, Map<Long, List<Long>> arvoreDeCategorias) {
        categorias.forEach(departamento -> {
            arvoreDeCategorias.put(departamento.getCodigoCategoria(), Arrays.asList(departamento.getCodigoCategoria()));

            if (!ObjectUtils.isEmpty(departamento.getSubCategorias()) || !departamento.getSubCategorias().isEmpty()) {
                departamento.getSubCategorias().forEach(categoria -> {
                    arvoreDeCategorias.put(categoria.getCodigoCategoria(),
                            Arrays.asList(categoria.getCodigoCategoria(), departamento.getCodigoCategoria()));

                    if (!ObjectUtils.isEmpty(categoria.getSubCategorias()) || !categoria.getSubCategorias().isEmpty()) {
                        categoria.getSubCategorias().forEach(subCategoria -> {
                            arvoreDeCategorias.put(subCategoria.getCodigoCategoria(),
                                    Arrays.asList(subCategoria.getCodigoCategoria(), categoria.getCodigoCategoria(), departamento.getCodigoCategoria()));
                        });
                    }
                    return;
                });
                return;
            }
            associarCategorias(departamento.getSubCategorias(), arvoreDeCategorias);
        });
    }

Basically you are looking into something that implements a deep-first traversal and then spit out the id stack as you move into the next recursion. This might best implemented using a regular recursion (if not too deep) or an iterative version using Stack data-structure to keep the id stack as you move along the traversal.

Pseudo-code:

final Map<Integer, List<Integer>> categoriesMaps(final JsonNode node, final Stack<Integer> parentIds, final Map<Integer, List<Integer>> dest) {
    dest.put(node.categoryId, new ArrayList<>(parentIds));
    parentIds.push(node.categoryId)
    for (final Node child : node.children()) {
        categoriesMaps(child, parentIds, dest);
    }
    parentIds.pop(); // removes node.categoryIds
}

I don't think this is the best use of lambda/stream specially if the maximum depth is unknown at compilation time and may vary between "leafs" ID.

Perhaps the best way to get this seemly done with stream is create your own Spliterator that would produced the wanted stream of LeafIds -> parentIDStackList pairs that then you can collect into a map if that is what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM