从排序的ArrayList中删除重复项,同时保留重复项中的一些元素

好吧,一开始我觉得这很简单。 但我想不出解决这个问题的有效方法。 我想出了一种蛮力的方法来解决这个问题,但这并不是很优雅。 我有一个ArrayList。 Contacts是一个VO类,有多个成员 – 名称,区域,ID。 ArrayList中存在重复项,因为不同的区域会多次出现。 该列表按ID排序。 这是一个例子:

第0条 – 姓名:约翰史密斯; 地区:N; ID:1
第1条 – 姓名:John Smith; 地区:MW; ID:1
第2条 – 姓名:John Smith; 地区:S; ID:1
第3条 – 姓名:Jane Doe; 区域:NULL; ID:2
第4条 – 姓名:Jack Black; 地区:N; ID:3
第6条 – 姓名:Jack Black; 地区:MW; ID:3
第7条 – 姓名:Joe Don; 地区:NE; ID:4

我想通过将重复区域组合在一起来将列表转换为相同的ID。 因此,最终列表应该只有4个不同的元素,并且区域组合在一起。

所以输出应该是这样的: –

第0条 – 姓名:约翰史密斯; 区域:N,MW,S; ID:1
第1条 – 姓名:Jane Doe; 区域:NULL; ID:2
第2条 – 姓名:Jack Black; 区域:N,MW; ID:3
第3条 – 姓名:Joe Don; 地区:NE; ID:4

您对解决此问题的最佳方法有何看法? 我不是在寻找实际的代码,而是寻找最佳方法来完成它的想法或提示。

谢谢你的时间!!!

您可以在将它们(并合并重复项)转储到TreeMap中时迭代它们。 然后从TreeMap的值的排序视图中创建一个列表。

在示例代码中,我假设您有一个带有id,name和regions字段的Entry类,最后一个是Region实例列表。 这可以很容易地更改为Set,Region to Strings或您正在使用的任何内容。 该示例在将条目插入到映射之前复制条目,因为它们将在合并到其他条目时进行修改。

SortedMap mergedEntriesMap = new TreeMap(); for (Entry e : entries) { if (mergedEntriesMap.contains(e.id)) { Entry m = mergedEntriesMap.get(e); m.regions.addAll(e.regions); } else { Entry m = new Entry(); // copy the entry to keep the original array clean m.id = e.id; m.name = e.name; m.regions = new ArrayList(e.regions); mergedEntriesMap.put(m.id, m); } } List mergedEntries = new ArrayList(mergedEntriesMap.values()); 

初始数据是否符合此格式? 如果没有,您可能希望通过将所有ID组合在一起并形成逗号分隔列表列来查看更改您用于检索数据的查询。 这是sql中的一个例子

 SELECT Id, [Name], Regions = replace ((SELECT Region AS [data()] FROM RegionTable WHERE Id = u.Id ORDER BY Region FOR xml path('')), ' ', ', ') FROM [User] u WHERE Id IS NOT NULL GROUP BY Id, [Name] 

这是一个完成你想要的伪代码。 在抽象层面,你有一个Pair (first, second) ,按K排序,没有两对真正相等(即你可以有(k1,v1)(k1,v2) ,但你不能在列表中有两个(k1,v1)

您希望将连续对(k,v1),(k,v2),(k,v3)合并为一个组(k,[v1,v2,v3])

 List> in; List>> out = [ ]; Pair lastP = SENTINEL_PAIR; // lastP.first matches nothing Pair> lastGroup; for (Pair p : in) { if (p.first == lastP.first) { // same group as last lastGroup.second.add(p.second); } else { // start a new group lastGroup = (p.first, [ p.second ]); out.add(lastGroup); } lastP = p; } 

在您的情况下, K是ID, V是区域。 这是O(N)

你看过google的Multimap吗? 它几乎是为这种类型的数据结构创建的,其中有一个键映射到项目Collection 。 因此,在这种情况下, String名称将映射到Region of Region对象。

 Multimap names = HashMultimap.create(); for (Entry entry : entries) { names.put(entry.getName(), entry.getRegion()); } // Now u can get the collection of regions by name Collection johnsRegions = names.get("John Smith");