【问题标题】:Remove Duplicates from ArrayList of ArrayLists [duplicate]从 ArrayList 的 ArrayList 中删除重复项 [重复]
【发布时间】: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]

感谢任何帮助。谢谢

【问题讨论】:

    标签: java arraylist duplicates


    【解决方案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>插入顺序。这意味着结果是按字母排序的,而不是原始列表中的排序。
        猜你喜欢
        • 2015-12-12
        • 1970-01-01
        • 1970-01-01
        • 2020-03-06
        • 1970-01-01
        • 1970-01-01
        • 2016-07-08
        • 2017-03-29
        • 1970-01-01
        相关资源
        最近更新 更多