无法使用递归

时间:2018-06-18 23:47:29

标签: java arraylist hashmap

我无法获得"祖父母"一个孩子。

//main class
User finalAlternate = new User();
        for(User user: userList) {
            if(user.getAlternateContactId() != null) {
                finalAlternate = checkAlternate(user);
                approverMap.put(finalAlternate.getId(), user.getId());
            }
        }

//helper method
public User checkAlternate(User user) { //returns the alternate
        User alternateUser = new User();
        if(user.getAlternateContactId() != null) {
            alternateUser = userMQService.getUser(user.getAlternateContactId(), new UserCollection[]{UserCollection.ROLES, UserCollection.GROUPS});
        } else {
            return user;
        }
        return checkAlternate(alternateUser);

    }

我有一组看起来像这样的用户:

User A -> User B -> User C

由于他们的替代联系人ID,所有这些用户都相互关联。因此,用户A的alternateContactId是用户B的ID,用户B的alternateContacId是用户C的ID。当我运行我的方法时,我的地图的结果如下所示:

 User C -> User B

那么,我如何修复我的方法,使地图看起来像这样:

User C -> User A

基本上我如何修复我的方法,这样才能得到任何孩子的第一个祖先?

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您将创建的用户存储在hashMap中并为每个用户提供唯一标识符,我选择使用每次使用时增加1的整数。

以下是一个示例实现,旨在帮助您入门:

public class User {

    private static final HashMap<Integer, User> hashMap = new HashMap();
    private static int index = 0;
    private static int NO_PARENT = -1;

    public final String name;
    public final int id;
    public final int parentId;

    public User(String name) {
        this.name = name;
        this.id = ++index;
        this.parentId = NO_PARENT;
        hashMap.put(id, this);
    }

    public User(String name, int parentId) {
        this.name = name;
        this.id = ++index;
        this.parentId = parentId;
        hashMap.put(id, this);
    }

    private User getGrandParent(User u, int generation) {
        if (generation == 2)
            return u;
        if (u != null && u.parentId != NO_PARENT)
            return getGrandParent(hashMap.get(u.parentId), generation +1);
        return null;
    }

    public User getGrandParen() {
        return getGrandParent(this, 0);
    }
}

测试

public static void main(String[] args) {
    User u1 = new User("A");
    User u2 = new User("B", u1.id);
    User u3 = new User("C", u2.id);
    User u4 = new User("D", u3.id);
    System.out.println("grandparent of C is: " + u3.getGrandParen().name);
    System.out.println("grandparent of D is: " + u4.getGrandParen().name);
}

输出:

grandparent of C is: A
grandparent of D is: B

请注意,您必须刷新不再需要的用户的HashMap。

我不清楚你的userMQService做了什么,如果它是异步任务,那么它是一个完整的游戏,但你指定了HashMap和数组,所以我假设你想要这样的东西。

要获得第一个祖先:

private User getFirstAncestor(User u) {
    if (u != null && u.parentId != NO_PARENT)
        return getFirstAncestor(hashMap.get(u.parentId));
    return u;
}

public User getFirstAncestor() {
    if (parentId == NO_PARENT) 
        return null; // there is no ancestry.
    return getFirstAncestor(this);
}

这是另一个不修改User类的示例:'

public class UserAncestry {
private static final HashMap<User, User> mapParent = new HashMap<>();

public static void setParent(User child, User parent) {
    mapParent.put(child, parent);
}

public static User getParent(User user) {
    return mapParent.get(user);
}

public static User getFirstAncenstor(User user) {
    User parent = mapParent.get(user);
    if (parent != null)
        return getFirstAncenstor(parent);
    return user;
}

}

public static void main(String[] args) {
    User u1 = new User("A");
    User u2 = new User("B");
    User u3 = new User("C");
    User u4 = new User("D");
    UserAncestry.setParent(u2, u1);
    UserAncestry.setParent(u3, u2);
    UserAncestry.setParent(u4, u3);
    User uu1 = UserAncestry.getFirstAncenstor(u4);
    User uu2 = UserAncestry.getFirstAncenstor(u3);
    System.out.println("uu1:: " + uu1.name);
    System.out.println("uu1:: " + uu2.name);
}

答案 1 :(得分:1)

问题是您正在覆盖Child/GrandParent地图中的先前条目。例如。

User finalAlternate = new User();
for(User user: userList) {
    if(user.getAlternateContactId() != null) {
        // Assuming the users are in the following order in the list [A, B, C]
        // In the first iteration you pass A
        finalAlternate = checkAlternate(user); 
        // checkAlternate(A) will traverse A->B->C until it finds C, so when
        // this method returns, finalAlternate should be equal to C.
        // All good! that is what we wanted

        // After the first iteration we have approveMap.put(C, A);
        approverMap.put(finalAlternate.getId(), user.getId());
    }
}

在第二次迭代中

for(User user: userList) {
    if(user.getAlternateContactId() != null) {
        // In the second iteration you pass B
        finalAlternate = checkAlternate(user); 
        // checkAlternate(B) will traverse B->C until it finds C, so when
        // this method returns, finalAlternate should be equal to C.


        // After the second iteration we have approveMap.put(C, B); // here is the problem
        approverMap.put(finalAlternate.getId(), user.getId());
    }
}

当且仅当,您的列表按照祖父母在父母之前出现的方式进行排序,然后对containsKey进行简单检查应该可以做到这一点:

if(!approveMap.containsKey(finalAlternate.getId()) {
    approverMap.put(finalAlternate.getId(), user.getId());
}

但是我不知道这是否会对你有所帮助,因为在列表中,祖父母可能会显示父母,例如[B, A, C]会给你“正确”的输出。要解决此问题,您可以为每个parent添加User字段,然后通过设置每个祖父母的User来检查parent是否为祖父母。 Usernull

public class User {

    private User parent = null; // all grandparent users should have parent = null;

    // .. some good code

    public boolean isGrandparent() {
        return parent == null;
    }
}

然后你可以添加那个比较

if(user.isGrandparent()) {
    approverMap.put(finalAlternate.getId(), user.getId());
}