Java:递归地迭代映射

Java:递归地迭代映射,java,algorithm,recursion,Java,Algorithm,Recursion,我们有一个看起来像“递归”数据结构的对象 假设有一个Person对象,其结构如下 public class Person { private String id; private Map<String,Person> persons; public Person(String id, Map<String,Person> persons){ this.id = id; this.persons = persons

我们有一个看起来像“递归”数据结构的对象

假设有一个Person对象,其结构如下

public class Person {
    private String id;

    private Map<String,Person> persons;

    public Person(String id, Map<String,Person> persons){
        this.id = id;
        this.persons = persons;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Map<String, Person> getPersons() {
        return persons;
    }

    public void setPersons(Map<String, Person> persons) {
        this.persons = persons;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", persons=" + persons + "]";
    }

}
注1:
ImmutableMap
来自google guava collection

注2:假设Person对象中映射的“键”是Person的名称

给定此人的姓名,迭代并获取id的最有效方法是什么。


例如,如果输入是“EVE”,那么输出应该是Ne'Y01'

因为您已经使用番石榴,请考虑将这样的方法添加到<代码>人< /代码>类:

public FluentIterable<Map.Entry<String, Person>> tree() {
    if (persons == null)
        return FluentIterable.from(ImmutableList.of());
    return FluentIterable.from(persons.entrySet())
            .transformAndConcat(
                entry -> Iterables.concat(ImmutableList.of(entry), entry.getValue().tree()));
}
或者使用
fluentiable
操作:

System.out.println(p1.tree()
                     .firstMatch(e -> e.getValue().getId().equals(name))
                     .get().getKey());

你的结构实际上是一种树。因此,您可以使用排序树的标准方法。如果您的树是一个二叉树(看起来不是),您可能能够非常有效地实现这一点

下面的方法行得通,但我没有证据证明它是最有效的方法。非二叉树大多只需要插入

效率取决于您认为递归性的堆叠程度。如果您认为大多数结构与示例结构相似,即:非常深,但每个级别只有几个人,这将非常有效。特别是如果你的结果接近底部

public String iterate(String name) {
        if (persons != null) {
            for (Entry<String, Person> entry : persons.entrySet()) {
                Person value = entry.getValue();
                if (value.getId().equals(name)) {
                    return entry.getKey(); //Since the key of each map is the ID when they return the key
                } else {
                    String ans = value.iterate(name);
                    if (ans != null) {
                        return ans;
                    }
                }
            }
        }
        return null;
    }
公共字符串迭代(字符串名称){
如果(人!=null){
for(条目:persons.entrySet()){
Person value=entry.getValue();
if(value.getId().equals(name)){
return entry.getKey();//因为每个映射的键都是返回键时的ID
}否则{
字符串ans=value.iterate(名称);
如果(ans!=null){
返回ans;
}
}
}
}
返回null;
}
它可以快速浏览整个人员列表堆栈,而无需返回顶部

但是,如果您有一个广泛的设置,并且您认为您的值将大部分接近顶部,那么您可以使用以下内容

public String iterate(String name) {
        if (persons != null) {
            for (Entry<String, Person> entry : persons.entrySet()) {
                Person value = entry.getValue();
                if (value.getId().equals(name)) {
                    return entry.getKey(); //Since the key of each map is the ID when they return the key
                }
            }

            for (Entry<String, Person> entry : persons.entrySet()) {
                String ans = entry.getValue().iterate(name);
                if (ans != null) {
                    return ans;
                }
            }
        }
        return null;
    }
公共字符串迭代(字符串名称){
如果(人!=null){
for(条目:persons.entrySet()){
Person value=entry.getValue();
if(value.getId().equals(name)){
return entry.getKey();//因为每个映射的键都是返回键时的ID
}
}
for(条目:persons.entrySet()){
字符串ans=entry.getValue().iterate(名称);
如果(ans!=null){
返回ans;
}
}
}
返回null;
}
这将允许快速找到结构顶部附近的东西,但在结构底部找到人的速度较慢


我猜你会想要更高的解决方案,它更标准。然而,我不认为他们之间有很大的区别。有关它的另一个版本,请参阅关于遍历树。

这对于番石榴的
树遍历者来说是一个完美的工作:

Iterable<Person> allPersons = new TreeTraverser<Person>() {
  @Override public Iterable<Person> children(Person p) {
     return p.getPersons().values();
  }
}.preOrderTraversal(rootPerson);
for (Person p : allPersons) {
  if (p.getId().equals(id)) {
    return p;
  }
}
Iterable allPersons=new TreeTraverser(){
@覆盖公共Iterable子项(人员p){
返回p.getPersons().values();
}
}.preOrderTraversal(rootPerson);
对于(人员p:所有人员){
if(p.getId().equals(id)){
返回p;
}
}

你可以让人们在他们的
地图中直接或间接地出现循环吗?到目前为止你做了什么?你知道
TreeTraverser
已经为你做了大部分工作了吗?@LouisWasserman,别担心,我已经高估了你的答案:-)它比我的答案短不了多少,但事实上,使用专用功能更好。但是请注意,OP实际上也需要输入键,所以您的答案实际上并不能解决他的问题。也许你应该编辑它。
public String iterate(String name) {
        if (persons != null) {
            for (Entry<String, Person> entry : persons.entrySet()) {
                Person value = entry.getValue();
                if (value.getId().equals(name)) {
                    return entry.getKey(); //Since the key of each map is the ID when they return the key
                } else {
                    String ans = value.iterate(name);
                    if (ans != null) {
                        return ans;
                    }
                }
            }
        }
        return null;
    }
public String iterate(String name) {
        if (persons != null) {
            for (Entry<String, Person> entry : persons.entrySet()) {
                Person value = entry.getValue();
                if (value.getId().equals(name)) {
                    return entry.getKey(); //Since the key of each map is the ID when they return the key
                }
            }

            for (Entry<String, Person> entry : persons.entrySet()) {
                String ans = entry.getValue().iterate(name);
                if (ans != null) {
                    return ans;
                }
            }
        }
        return null;
    }
Iterable<Person> allPersons = new TreeTraverser<Person>() {
  @Override public Iterable<Person> children(Person p) {
     return p.getPersons().values();
  }
}.preOrderTraversal(rootPerson);
for (Person p : allPersons) {
  if (p.getId().equals(id)) {
    return p;
  }
}