从 ArrayList 的 ArrayList 中删除重复项 [重复]
Posted
技术标签:
【中文标题】从 ArrayList 的 ArrayList 中删除重复项 [重复]【英文标题】:Remove Duplicates from ArrayList of ArrayLists [duplicate] 【发布时间】:2018-05-29 22:30:52 【问题描述】:我有一个问题,我确信解决方案很简单,但我找不到。我有一个较小的ArrayList
s 的ArrayList
。这些列表包含String
类型的元素。我想将较小的列表合并为一个,然后删除重复项。让我说清楚。
我有这个:
[[USA, Maine], [USA, Maine, Kennebunk], [USA, Maine, North Berwick],
[USA, New Hampshire], [USA, Keene, New Hampshire], [USA, Keene, New
Hampshire, Main Street], [USA, New Hampshire, Swanzey]].
这是我的主列表,里面有较小的列表。我想要一个最终的ArrayList
,它是较小的合并并删除重复项。
我想要的是:
[USA, Maine, Kennebunk, North Berwick, New Hampshire , Keene, Main Street, Swanzey]
感谢任何帮助。谢谢
【问题讨论】:
【参考方案1】:如果您的目标是ArrayList 的实例,我们称之为“resultList”。然后遍历每个内部ArrayLists
并仅添加这些Strings
,contains()
方法返回false。只有当您必须使用ArrayList
作为您的最终收藏时,这才是解决方案。否则,您应该考虑使用HashSet
,它会自动在内部保存唯一值并删除任何重复的对象。如果您需要使用ArrayList
作为结果集合,以下代码可能会对您有所帮助:
ArrayList<ArrayList<String>> sourceList = new ArrayList<>();
// Adding sample ArrayLists ("a" and "b") of Strings to sourceList:
ArrayList<String> a = new ArrayList<>();
a.add("USA");
a.add("Maine");
sourceList.add(a);
ArrayList<String> b = new ArrayList<>();
b.add("USA");
b.add("Maine");
b.add("Kennebunk");
sourceList.add(b);
ArrayList<String> resultList = new ArrayList<>();
for(ArrayList<String> outerList : sourceList)
for(String str : outerList)
// If resultList doesn't contain currently checked string...
if(!(resultList.contains(str)))
// Add this string to resultList...
resultList.add(str);
System.out.println(resultList.toString());
你得到的输出:[USA, Maine, Kennebunk]
【讨论】:
是的,我必须使用 ArrayList 作为我的最终集合。关于代码你有什么想法吗? 您可以使用两个嵌套的 foreach 循环。在外部列表中,您迭代外部 ArrayList,在内部列表中,您迭代每个内部列表。在内部循环体中,您检查最终的 ArrayList 是否已经包含字符串,如果没有,则将其添加到 ArrayList【参考方案2】:我看到了这个帖子,不得不回答,Berwick/Kennebunk 是我住过的城镇,哈哈。你是本地人吗?
无论如何,最简单的方法是使用上面提到的集合操作。这保证了一些 O(log n) 搜索。
public List<String> mergeTowns (List<List<String>> list)
Set<String> uniques = new HashSet<>();
for(List<String> sublist : list)
uniques.addAll(sublist);
return new ArrayList<>(uniques);
如果您正在寻找更动态的数据结构,请使用地图,其中国家是您的关键,城镇是您的价值。这样,如果您决定按不同国家/地区建立城镇大数据库,然后按国家/地区搜索地图以显示城镇。也许使用 State 而不是 country 作为您的密钥。
生成的数据结构会放弃这样的地图。打印时。
[美国 = [贝里克、肯纳邦克、北贝里克、威尔斯]、加拿大 = [贝里克、肯纳邦克、北贝里克、威尔斯]、墨西哥 = [贝里克、肯纳邦克、北贝里克、威尔斯]]
数据结构的构建方式可防止在同一国家/州出现重复的城镇条目。
public class Merge
private static ArrayList<String> mergeMap(HashMap<String, Set> map)
ArrayList<String> data = new ArrayList();
for(Entry<String, Set> entries : map.entrySet())
String country = entries.getKey();
Set<String> towns = entries.getValue();
data.add(country+" = "+towns);
return data;
public static void main(String[] args)
//Mock data
String[] countrys = "USA", "CANADA", "MEXICO";
//Try this way of building your data structure instead of an array list of array list.
HashMap<String,Set> map = new HashMap<String,Set>();
TreeSet<String> towns = new TreeSet<String>();
// Add a couple towns to your set of towns
towns.add("berwick");
towns.add("north berwick");
towns.add("kennebunk");
towns.add("kennebunk");
towns.add("kennebunk");
towns.add("kennebunk");
towns.add("wells");
towns.add("wells");
//With a map you could push a different set of towns to different countries
for(String country: countrys)
map.put(country, towns);
//Pass in your map<Country, Towns>
ArrayList<String> mergedValues = mergeMap(map);
【讨论】:
【参考方案3】:传统解决方案:
Set<String> result = new LinkedHashSet<>();
for (List<String> innerList : filmingLocations) result.addAll(innerList);
由于result
是LinkedHashSet
,它保留了插入顺序,因此元素的顺序将与内部列表中的顺序相同。
您也可以使用等效的 Java 8 解决方案:
Set<String> result = new LinkedHashSet<>();
filmingLocations.forEach(result::addAll);
甚至是基于 Java 8 流的解决方案:
Set<String> result = filmingLocations.stream()
.flatMap(List::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
【讨论】:
谢谢,我知道 JDK 中有一些Set
保留插入顺序,但我不记得它的名字(他们在 Collection
或 @987654328 的 Javadoc 中没有提到它@,虽然他们这样做是为了HashSet
、TreeSet
甚至 SortedSet
) :-P【参考方案4】:
这是使用Stream
类的简洁解决方案:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toSet())
请注意,结果的类型为Set
。这负责删除重复项。
如果你需要List
,你可以使用这个:
listOfLists.stream()
.flatMap(List::stream)
.distinct()
.collect(Collectors.toList())
请注意,这甚至可以保证元素的顺序是稳定的,即[["foo","bar"],["bar","abc","foo"]]
将始终按此顺序生成["foo","bar","abc"]
。大多数使用Set
的解决方案不保证这一点,因为它们中的大多数都没有排序。
【讨论】:
我的 ArratLists ArrayList 称为 filmingLocations。这是我应该有代码的方式吗? filmingLocations.stream().flatMap(List::stream).distinct().collect(Collectors.toList(); @hristoforidisc,是的 :-) 此时 flatMap(List::stream) 出现错误。我应该进口什么吗? @hristoforidisc,上面的代码需要导入java.util.List
和java.util.stream.Collectors
。
我已经这样做了,但还是不行。【参考方案5】:
解决方案:
使用ArrayList的.contains()
方法在你的ArrayList的ArrayList中循环遍历ArrayList并将字符串添加到另一个ArrayList中
代码:
public ArrayList<String> merge(ArrayList<ArrayList<String>> startArrayList)
ArrayList<String> finalArrayList = new ArrayList<String>();
//Iterate over each element
for (ArrayList<String> innerList:startArrayList)
for (String value:innerList)
//add the String if it is missing
if (!finalArrayList.contains(value))
finalArrayList.add(value);
return finalArrayList;
【讨论】:
【参考方案6】:在 Set 的帮助下很容易执行(Set 不允许重复值)
public List<String> merge(List<List<String>> list)
Set<String> uniques = new HashSet<>();
for(List<String> sublist : list)
uniques.addAll(sublist);
return new ArrayList<>(uniques);
附言当您希望合并列表将被排序时,将 HashSet 更改为 TreeSet
像这样:Set<String> uniques = new TreeSet<>();
【讨论】:
请注意,TreeSet
使用元素的自然排序(或在构造时传递的其他一些Comparator
)并且不是 i>插入顺序。这意味着结果是按字母排序的,而不是原始列表中的排序。以上是关于从 ArrayList 的 ArrayList 中删除重复项 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Java ArrayList:从包含 HashMap 的 ArrayList 中获取不同的值
java - 如何从java中的另一个ArrayList中删除一个ArrayList的元素?