合并来自n个列表的HashMaps

时间:2011-04-27 22:11:59

标签: java list merge hashmap

我会尽力尽力描述我的问题,但请问是否有些事情没有意义。

  • 我的列表数量有限
  • 每个列表包含有限数量的联系人
  • 每个联系人都表示为HashMap
  • 每个列表都链接到提供商
  • 同一个联系人可能存在于多个提供者中(因此也有多个列表)。
  • 我需要一个'主'列表,其中包含其他列表中的所有唯一条目

我正在寻找一种有效的方法将这些列表合并到一个没有重复的主列表中。例如,如果相同的联系人出现在多个列表中(多个HashMaps对应于同一个物理人),我想将所有HashMaps合并为一个,并将合并后的HashMap放入主列表中。这里有一个简单的“putall”,因为我需要重新键入内容以便有效地访问它们(例如,提供者1给我一个电子邮件地址列表,键入为'电子邮件',提供者2给我相同的信息键入'的emailList')。

合并单个HashMaps更容易出现两个问题,因为我知道这些键并且可以轻松地合并它们。

让我摸不着头脑的问题是有效扫描列表...除了线性遍历嵌套循环中的每个列表,抓住下一个HashMap,检查它是否已存在于mater列表中之外没有别的方法了合并/创建一个新的......?

4 个答案:

答案 0 :(得分:1)

首先观察 - 使用HashMap来表示联系人气味"object denial"

您需要设计并实现Contact类来表示联系人。如果没有这门课程,你的任务就会比你需要的更加困难。

该类需要所有联系键字段的getter,并且需要根据键字段实现equals,hashcode和Comparable。非关键字段也需要Getters(以及可选的setter)。

这样,合并过程变为(伪代码):

// If you haven't already done so
convert the master list of HashMaps to a list of Contact objects and sort it.
create an empty "new master" list

for each list of contact HashMaps:
    convert the list of HashMaps to a merge list of Contact objects
    sort the merge list
    iterate the sorted master and merge lists in parallel:
        if a master Contact matches a merge Contact:
            merge the two Contacts and add to the new master list
            advance both iterators
        if a master Contact has no corresponding merge Contact:
            copy the master Contact to the new master list
            advance the master iterator.
        if a merge Contact has no corresponding master Contact:
            add the merge Contact to the new master list.
            advance the merge iterator

各阶段的表现特征应为:

  • 将N HashMaps转换为Contact对象 - O(N)
  • 创建N个联系人列表 - O(N)
  • N个联系人列表 - O(NlogN)
  • 合并2个排序列表 - O(M + N)

整体性能应优于O(NlogN),其中N是主客户对象和合并客户对象的总数。

答案 1 :(得分:0)

使用类似下面的类创建Map<String,Contact>。虽然,我仍然不确定提供商的意思。也许你可以提供更多细节。

class Contact {

    enum ContactMethod {
        email,
        phone,
        address
    }

    String name;
    Map<ContactMethod,Set<String>> contactInfo;

    Contact(String name) {
        this.name = name;
        this.contactInfo = new HashMap<ContactMethod,Set<String>>();
    }

    void consume(Map<ContactMethod,String> info) {
        for(ContactMethod method : info.keySet()) {
            Set<String> modes = contactInfo.get(method);
            if(modes == null) {
                modes = new HashSet<String>();
                contactInfo.put(method,modes);
            }
            modes.add(info.get(method));
        }
    }
}

答案 2 :(得分:0)

对于内部主列表,您是否可以使用一个类来定义一个有意义的equals()来封装HashMap,而不是直接存储HashMaps?如果这样做,您可以切换到使用具有主列表的常量查找(例如,HashSet)的Collection实现。这将消除嵌套迭代,您只需要检查一次提供者的每个联系人。确定您的联系人数量是否足够大以至于是一种改进,这是一种反复试验。

答案 3 :(得分:0)

如果您的列表已排序,请考虑以下事项:

创建一个“合并”迭代器,它会从列表中消耗2个迭代器 如果两个头是相同的,扔一个。否则出现两者中较小的一个 如果一个头部来自耗尽的(空的)迭代器,则只需显示另一个头部。

现在你有一个迭代器,它从2个迭代器产生一个唯一的排序序列。

您可以根据需要将这些内容堆积起来,以便为所有列表获取唯一的迭代器。