将对列表转换为分组对列表

时间:2018-01-12 11:46:15

标签: java algorithm list stream converter

我找不到这个问题的好线程名称:C 我有两个具有长值的字段的对象列表:

class ObjectFromDb {
    Long dbUserId;
    Long apiUserId;
}

EG。它看起来像这样:

List<ObjectFromDb> dbList = {
    {1, 1},
    {2, 2},
    {2, 3},
    {3, 4},
    {4, 4},
    {5, 4},
    {6, 5}
}

目标是将此列表分组为关系。可能性是: 一对一,一对多,多对一。允许的人数并不多。

我的最终目标:

class FinalObject {
    List<Long> dbIds;
    List<Long> apiIds;
}

所以结果列表应该是:

List<FinalObject> finalList = {
    { {1}    , {1}   },
    { {2}    , {2,3} },
    { {3,4,5}, {4}   },
    { {6}    , {5}   }
}

这是我的问题。有没有算法来解决这样的问题?或者,如果有人知道如何处理它?我试图解决它,但最终得到了十亿ifs和for循环,所以我再次开始并最终得到另外十亿个循环..

2 个答案:

答案 0 :(得分:1)

以下是解决方案的想法:

第1步(多对一关系):根据dbList排序dbUserID,将apiUserIdsdbUserID合并,并从{{1}中删除相应的关系(在代码中我构建了一个名为dbList的新列表)。

第2步(一对多关系):根据updatedDbList1dbList进行排序,将apiUserIddbUserIDs结合使用,并从{{1}中删除相应的关系(在代码中我构建了一个名为apiUserIds的新列表)。

步骤3(一对一关系):将剩余关系添加到最终结果中。

这就是我想出来的,虽然我确信可以通过多一点思考来做得更干净。

dbList

答案 1 :(得分:1)

我不确定您的算法是否涵盖了涵盖所有可能性的关系,但这里是提供所需输出的代码。

我解释了它的作用以及它如何与评论一起使用。

  // First it is gonna group dbUserIds and apiUserIds between each other. To keep this data, we are gonna use hashMaps
        Map<Long, List<Long>> dbUserIdGroup = new HashMap<Long, List<Long>>();
        Map<Long, List<Long>> apiUserIdGroup = new HashMap<Long, List<Long>>();

        // To demonstrate the test data given by you
        List<ObjectFromDb> dbList = new ArrayList<ObjectFromDb>();
        dbList.add(new ObjectFromDb(1L, 1L));
        dbList.add(new ObjectFromDb(2L, 2L));
        dbList.add(new ObjectFromDb(2L, 3L));
        dbList.add(new ObjectFromDb(3L, 4L));
        dbList.add(new ObjectFromDb(4L, 4L));
        dbList.add(new ObjectFromDb(5L, 4L));
        dbList.add(new ObjectFromDb(6L, 5L));

        // Iterating the given ObjectFromDb instances to group them 
        for (ObjectFromDb objectFromDb : dbList) {

            // Grouping according to dbUserId
            if (dbUserIdGroup.get(objectFromDb.getDbUserId()) == null) {
                List<Long> group = new ArrayList<Long>();
                group.add(objectFromDb.getApiUserId());
                dbUserIdGroup.put(objectFromDb.getDbUserId(), group);
            } else {
                dbUserIdGroup.get(objectFromDb.getDbUserId()).add(objectFromDb.getApiUserId());
            }

            // Grouping according to apiUserId
            if (apiUserIdGroup.get(objectFromDb.getApiUserId()) == null) {
                List<Long> group = new ArrayList<Long>();
                group.add(objectFromDb.getDbUserId());
                apiUserIdGroup.put(objectFromDb.getApiUserId(), group);
            } else {
                apiUserIdGroup.get(objectFromDb.getApiUserId()).add(objectFromDb.getDbUserId());
            }
        }

        // Up to now, we have two grouped hashmaps 
        // dbUserIdGroup ->  {"1":[1],"2":[2,3],"3":[4],"4":[4],"5":[4],"6":[5]} // note that the key of this hashtable is dbUserId
        // apiUserIdGroup ->  {"1":[1],"2":[2],"3":[2],"4":[3,4,5],"5":[6]} //  note that the key of this hashtable is apiUserId
        Set<Long> dbUserIds = dbUserIdGroup.keySet(); // to iterate dbUserId group we get its keys (dbUserIds)

        Set<List<Long>> existanceCheck = new HashSet<>(); // to avoid duplicated data

        List<FinalObject> result = new ArrayList<FinalObject>(); // to keep the result
        for (Long dbUserId : dbUserIds) {
            FinalObject fObject = null;
            List<Long> dbApiIdList = dbUserIdGroup.get(dbUserId);

            if (dbApiIdList.size() == 1) { // if the value is the list with single element
                List<Long> groupedDbUserId = apiUserIdGroup.get(dbApiIdList.get(0));
                if (!existanceCheck.contains(groupedDbUserId)) {
                    fObject = new FinalObject(groupedDbUserId, dbApiIdList);
                    existanceCheck.add(groupedDbUserId);
                    result.add(fObject);
                }
            } else { // if the value is the list with multiple elements
                List<Long> dbUserIdList = new ArrayList<Long>();
                dbUserIdList.add(dbUserId);
                fObject = new FinalObject(dbUserIdList, dbApiIdList);
                result.add(fObject);
            }

        }

        // Now you have a List<FinalObject> result array just like you want.