简体   繁体   English

Java 在列表中克隆 Object N 次

[英]Java Clone Object inside a list N times

I have this object我有这个 object

public class Menu implements Cloneable{
String id;
String repetable;
List <Menu> children;

//Getters and Setters

public Menu clone() {
    Menu obj = null;
    try {
      obj = (Menu)super.clone();
    }catch (CloneNotSupportedException e) {
      throw new RuntimeException();
    }
    return obj;
  }
}

As you can see this object have a list inside of the same item so it is a recursive list.如您所见,这个 object 在同一项目中有一个列表,因此它是一个递归列表。

The logic I am implementing recieve as an input param the object Menu as a list, inside there can be N children.我正在实施的逻辑将 object 菜单作为输入参数接收为列表,其中可以有 N 个子项。

What I need to achieve is clone the object if the field "repetable" is different from NULL or Empty.如果字段“可重复”不同于 NULL 或 Empty,我需要实现的是克隆 object。 I need to iterate the whole list, process each object one by one apply the filter (by field repetable) and then clone the object and append it to the list in other words.我需要迭代整个列表,一个一个地处理每个 object 应用过滤器(按字段可重复),然后将 object 和 append 克隆到列表中,换句话说。

The twist here is that I need to clone the Item N times, based on a int value given during the execution.这里的转折点是我需要根据执行期间给出的 int 值将 Item 克隆 N 次。

Here is what I got so far.这是我到目前为止得到的。

private List<Menu> cloneElementsInListNTimes(List<Menu> sourceList) {

    List <Menu> srList = sourceList;
    List<Menu> repetableList = new ArrayList<>();

    srList.stream()
          .peek(p -> p.setChildren(cloneElementsInListNTimes(p.getChildren())))
          .map(obj -> {
            int objectRepetitions = 2;
            return cloneObject(obj, objectRepetitions);
          })
          .filter(p -> StringUtils.isNotEmpty(p.getRepetable()))
          .forEachOrdered(repetableList::add);

    sourceList.addAll(repetableList);
    return sourceList;
  }

Here is the cloneObject method.这是 cloneObject 方法。

private ConfigurationMenuRs cloneObject(Menu obj, int repetableTimes) {
    for (int j = 0; j < repetableTimes; j++) {
      obj.clone();
    }
    return obj;
  }

List Data example:列表数据示例:

Input:输入:

[
    {
        "id": "1",
        "repetable": "",
        "children": [
            {
                "id": "1.1",
                "repetable": "Yes",
                "children": []
            },
            {
                "id": "1.2",
                "repetable": "",
                "children": []
            }
        ]
    },
    {
        "id": "2",
        "repetable": "Yes",
        "children": []
    },
    {
        "id": "3",
        "children": []
    }
]

Output: Output:

[
    {
        "id": "1",
        "repetable": "",
        "children": [
            {
                "id": "1.1",
                "repetable": "Yes",
                "children": []
            },
            {
                "id": "1.1",
                "repetable": "Yes",
                "children": []
            },
            {
                "id": "1.1",
                "repetable": "Yes",
                "children": []
            },
            {
                "id": "1.2",
                "repetable": "",
                "children": []
            }
        ]
    },
    {
        "id": "2",
        "repetable": "Yes",
        "children": []
    },
    {
        "id": "2",
        "repetable": "Yes",
        "children": []
    },
    {
        "id": "2",
        "repetable": "Yes",
        "children": []
    },
    {
        "id": "3",
        "children": []
    }
]

As can see the object with id 1.1 and 2 where cloned two times.可以看到 id 为 1.1 和 2 的 object 被克隆了两次。 That is because of the value 2 set on the method cloneObject.这是因为在方法 cloneObject 上设置了值 2。

I know I am missing the exact logic to clone a object N times and how to add it or append it to the current list, but I cant figure out how I can achieve this.我知道我缺少克隆 object N 次以及如何将它或 append 添加到当前列表的确切逻辑,但我无法弄清楚如何实现这一点。

EDIT编辑

Using a for to iterate over the principal array (input) I manage to get the response I am looking for.使用 for 遍历主数组(输入),我设法获得了我正在寻找的响应。

private List<Menu> cloneElementsInListNTimes(List<Menu> sourceList,
      HashMap<String, String> contextData) {

    List <Menu> srList = sourceList;
    List<Menu> repetableList = new ArrayList<>();

    for (int i = 0; i < sourceList.size(); i++) {
      Menu m = srList.get(i);
      if(StringUtils.isNotEmpty(m.getRepeatableBy())){
        m.setChildren(cloneElementsInListNTimes(m.getChildren(), contextData));
        List<Menu> cloned = cloneObject(m, 2);
        repetableList.addAll(cloned);
      }
    }

    sourceList.addAll(repetableList);
    return sourceList;
  }

private List<Menu> cloneObject(Menu item, int i) {
    List<Menu> clonedList = new ArrayList<>();
    for (int j = 0; j < i; j++) {
      item.clone();
      clonedList.add(item);
    }
    return clonedList;
  }

What I would want to know now is that if there is a way to optimize this, maybe using java 8 streams.我现在想知道的是,如果有办法对此进行优化,也许可以使用 java 8 个流。

Following is a working example:以下是一个工作示例:

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        // Create the menus...
        // First menu with its 2 children
        Menu menu11 = new Menu("1.1", true, List.of());
        Menu menu12 = new Menu("1.2", false, List.of());
        Menu menu1 = new Menu("1", false, List.of(menu11, menu12));

        // Second and third menu, no children.
        Menu menu2 = new Menu("2", true, List.of());
        Menu menu3 = new Menu("3", false, List.of());

        List<Menu> sourceList = List.of(menu1, menu2, menu3);
        List<Menu> clonedElements = cloneElementsInListNTimes(sourceList, 2);

        // Print result
        System.out.println("[");
        for (Menu m : clonedElements) {
            m.printMenu(0);
        }
        System.out.println("]");
    }


    private static List<Menu> cloneElementsInListNTimes(List<Menu> sourceList, int N) {
        List<Menu> result = new ArrayList<>();
        for (Menu menu : sourceList) {
            List<Menu> children = menu.getChildren();
            List<Menu> clonedChildren = cloneElementsInListNTimes(children, N);
            menu.setChildren(clonedChildren);
            result.add(menu);
            if (menu.getRepeatable())
                result.addAll(cloneObject(menu, N));
        }
        return result;
    }

    
    private static List<Menu> cloneObject(Menu obj, int N) {
        List<Menu> cloned = new ArrayList<>();
        for (int j = 0; j < N; ++j) {
            cloned.add(obj.clone());
        }
        return cloned;
    }
}

Be aware of the fact that cloning in Java is a shallow copy of the object to clone, so cloneElementsInListNTimes will naturally also change sourceList ( Actually, the children of menus inside that list, because the method is setting new children for a menu, so we're referencing the same object ).请注意,克隆Java 是要克隆的 object 的浅拷贝,因此cloneElementsInListNTimes自然也会更改sourceList实际上,该列表中的菜单的子项,因为该方法正在为菜单设置新的子项,所以我们'引用相同的 object )。

Using Streams:使用流:

private static List<Menu> cloneElements(List<Menu> sourceList, int N) {
        List<Menu> result = new ArrayList<>();
        sourceList.stream()
                .peek(menu -> menu.setChildren(cloneElements(menu.getChildren(), N)))
                .forEach(menu -> {
                    result.add(menu);
                    if (menu.getRepeatable())
                        result.addAll(cloneObject(menu, N));
                });
        return result;
    }

The following alternative omits the if in the streams solution above, but clones first all the objects and then filters them out if they are not repeatable:以下替代方案省略了上面流解决方案中的if ,但首先克隆所有对象,然后在它们不可重复时将其过滤掉:

List<Menu> result = new ArrayList<>();
sourceList.stream()
          .peek(menu -> {
                    menu.setChildren(cloneElements(menu.getChildren(), N));
                    result.add(menu);
                }
           )
           .map(menu -> cloneObject(menu, N).stream().filter(menuInList -> menuInList.getRepeatable()))
           .forEach(menuStream -> result.addAll(menuStream.toList()));
        return result;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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