从 ArrayList 的 ArrayList 中删除重复项 [重复]

Posted

技术标签:

【中文标题】从 ArrayList 的 ArrayList 中删除重复项 [重复]【英文标题】:Remove Duplicates from ArrayList of ArrayLists [duplicate] 【发布时间】:2018-05-29 22:30:52 【问题描述】:

我有一个问题,我确信解决方案很简单,但我找不到。我有一个较小的ArrayLists 的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 并仅添加这些Stringscontains() 方法返回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);

由于resultLinkedHashSet,它保留了插入顺序,因此元素的顺序将与内部列表中的顺序相同。

您也可以使用等效的 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 中没有提到它@,虽然他们这样做是为了HashSetTreeSet 甚至 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.Listjava.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&lt;String&gt; uniques = new TreeSet&lt;&gt;();

【讨论】:

请注意,TreeSet 使用元素的自然排序(或在构造时传递的其他一些Comparator)并且不是 i>插入顺序。这意味着结果是按字母排序的,而不是原始列表中的排序。

以上是关于从 ArrayList 的 ArrayList 中删除重复项 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java ArrayList:从包含 HashMap 的 ArrayList 中获取不同的值

无法从ArrayList强制转换 到ArrayList

如何从arraylist中获取其中的一个元素

java - 如何从java中的另一个ArrayList中删除一个ArrayList的元素?

如果其他ArrayList中的条件为true,如何从ArrayList中删除项目

例外:从意图存储ArrayList时“无法转换为java.util.ArrayList”