【问题标题】:Find all levels of Children and add to ArrayList查找所有级别的 Children 并添加到 ArrayList
【发布时间】:2020-07-07 06:16:27
【问题描述】:

我有输入说

PARENT~CHILD
P1~C1
C1~C2
C2~C3
C3~C4
P2~C5
C5~C6
C6~C3

现在我需要找到所有级别的孩子并添加到MAP。如下所示

P1={C1,C2,C3,C4}
P2={C5,C6,C3,C4}

我尝试了下面的代码,我手动为其顶级父级添加子级。当数据更多时,这需要很多时间。我是 Java 新手,我不知道如何有效地做到这一点。我相信会有一些简单的方法来做到这一点。

HashMap<String,ArrayList<String>> map= new HashMap<String,ArrayList<String>>();
ArrayList<String> list =new ArrayList<String>();

list.add("C1");
list.add("C2");
list.add("C3");
list.add("C4")

map.put("P1",list); 

【问题讨论】:

  • 既然C3有子C4,那结果不就是P2={C5,C6,C3,C4}吗?如果不是,为什么不呢?你怎么知道C3~C4 不适用于P2 后代树?
  • 你是对的。 @安德烈亚斯。 P2 也应该有 C4。我已经编辑了这个问题。谢谢!
  • 父子如何存储?在地图中?
  • @vivek_23。你是说输入法?输入来自文本文件。我必须从文本文件中读取它,如果它更有效,我们可以保留在地图或其他方式中。

标签: java arraylist hashmap


【解决方案1】:

如果您不想在选择算法时使用 DFS 和 BFS 算法,则性能会更好。这是解决此类问题的简单方法。可能对你有帮助。

父子关系的模型类

    class Relation {
        String parent;
        String child;

        // constructor
        public Relation(String parent, String child) {
            super();
            this.parent = parent;
            this.child = child;
        }

       // setter getter toString methods

    }
    

实际实施

    public static Map<String, List<String>> getAllLevelOfChildren(List<Relation> relations){
        HashMap<String, List<String>> map = new HashMap<String, List<String>>();
        List<String> tempList = null;
        Set<String> parents = new HashSet<String>();
        Set<String> children = new HashSet<String>();
        
        for(Relation relation:relations){
            parents.add(relation.getParent());
            children.add(relation.getChild());
        }       
        parents.removeAll(children);        
        
        for(String key:parents){
            tempList = new ArrayList<String>();
            map.put(key, tempList);
        }
       // Relation between Parent Child
        for(Relation rel : relations){              
            if(parents.contains(rel.getParent())){
                tempList = map.get(rel.getParent());
                tempList.add(rel.getChild());
                map.put(rel.getParent(), tempList);
            }               
            for(String parent:parents){
                tempList = map.get(parent);
                if(tempList.contains(rel.getParent())){
                    tempList.add(rel.getChild());
                    map.put(parent, tempList);
                }
            }
        }

        // Relation between children
        for (Relation rel : relations) {
            for (String parent : parents) {
                tempList = map.get(parent);
                if (tempList.contains(rel.getParent()) && !tempList.contains(rel.getChild())) {
                    tempList.add(rel.getChild());
                    map.put(parent, tempList);
                }
            }       
        }
        
        return map;
    }

主要测试方法:

    public static void main(String[] args) {        
        List<String> list = Arrays.asList("P1~C1","C1~C2","C2~C3","C3~C4","P2~C5","C5~C6","C6~C3");
        System.out.println("Input List : "+list);
        List<Relation> relations = list.stream().map(o->{
            return new Relation(o.split("~")[0],o.split("~")[1]);
        }).collect(Collectors.toList());
        
        System.out.println("All level of Children : "+getAllLevelOfChildren(relations));    
    }

输出

Input List : [P1~C1, C1~C2, C2~C3, C3~C4, P2~C5, C5~C6, C6~C3]
All level of Children : {P1=[C1, C2, C3, C4], P2=[C5, C6, C3, C4]}

【讨论】:

  • 非常感谢。我会测试所有的情况并接受这个。
  • 这段代码有一个问题。它仅在 3 个级别的子子项之前有效。它不考虑后来的孩子。如何纠正?请推荐@Jimmy
  • @Avinash 根据此代码,级别 (>2) 取决于最后一个循环 e.i 子级之间的关系。如果您再次重复此循环,级别将增加到 4。绝对通用解决方案将是最佳选择.. 尝试从输入中找到级别并根据级别重复它
【解决方案2】:
  1. 将数据加载到父节点的Map&lt;String, List&lt;String&gt;&gt; 到直接子节点列表中,因为父节点可能有多个子节点。

  2. 识别所有没有父节点的节点,这将是结果映射中的“根父节点”键。

  3. 使用 DFS (Depth First Search) 或 BFS (Breath First Search),收集每个根父节点的所有后代。
    您可能希望将结果设为 Map&lt;String, Set&lt;String&gt;&gt; 以消除合并/循环分支的问题,除非保证不可能。

【讨论】:

  • +1。感谢你的回答。我真的是Java的初学者。不确定如何使用 DFS 或 BFS。你能提供与此相关的基本java代码吗?在维基百科链接中,我无法获得任何代码来实现相同的功能。我知道这可能是非常基本的,但我很无奈:(
  • @Avinash 两篇文章都包含伪代码,您只需将其编写为 Java 代码即可。
猜你喜欢
  • 2013-12-23
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多