【问题标题】:Find duplicate strings in list and make them unique在列表中查找重复的字符串并使其唯一
【发布时间】:2017-04-10 12:42:35
【问题描述】:

我有一个带有重复字符串值的ArrayList,并希望通过附加计数来使重复项唯一。

public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("d");
    list.add("b");
    list.add("c");
    list.add("a");
    list.add("a");
    list.add("a");

    HashSet<String> set = new HashSet<String>();
    List<String> duplicateList = new ArrayList<String>();

    for (String item : list) {
        // If String is not in set, add it to the list and the set.
        if (!set.contains(item)) {              
            set.add(item);
        } else {
            duplicateList.add(item);
        }
    }

    for (String element : duplicateList) {
        System.out.println(element);
    }
}

有没有办法让列表像:

a
b
c
d
b1
c1
a1
a2
a3

【问题讨论】:

  • 为什么要将数据存储在数组列表中?这是首先要开始的点。
  • @ThomasJunk。我想要具有重复值的列表。到底有没有?

标签: java list duplicates unique


【解决方案1】:

假设您使用 Java 8,如果您想获得 List 的每个值的重复总数,您可以通过按值分组来实现 Stream API然后将每个值的出现计数为下一个:

Map<String, Long> counter = list.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counter);

输出:

{a=4, b=2, c=2, d=1}

如果您想通过在原始String 的末尾添加一个计数器来防止重复,您可以使用LinkedHashSet 来保留Elliott Frisch 建议的值的顺序。

Elliott Frisch 的方法略有不同:

List<String> list = Arrays.asList("a", "b", "c", "d", "b", "c", "a", "a", "a");
Set<String> set = new LinkedHashSet<>();
for (String str : list) {
    String value = str;
    // Iterate as long as you can't add the value indicating that we have
    // already the value in the set
    for (int i = 1; !set.add(value); i++) {
        value = str + i;
    }
}
System.out.println(set);

输出:

[a, b, c, d, b1, c1, a1, a2, a3]

【讨论】:

    【解决方案2】:

    看来你的想法是对的。您只需要使用Map 并实际计算遇到的字符串,而不是仅仅指出遇到了它们:

    Map<String, Integer> counter = new HashMap<>();
    List<String> duplicateList = new ArrayList<>();
    
    for (String item : list) {
    
        // If String is not in set, add it to the list and the set, and 
        // note this is the first time it's encountered
        if (!counter.containsKey(item)) {
            duplicateList.add(item);
            counter.put(item, 1);
        } else {
            Integer count = counter.get(item);
            duplicateList.add(item + count);
            item.put(item, count + 1);
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用LinkedHashSet,也可以使用Arrays.asList(T...) 来初始化您的List。首先,检查集合是否包含来自list 的元素。如果是,迭代值,直到找到尚未出现的值。类似的,

      List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c", "d", 
              "b", "c", "a", "a", "a"));
      Set<String> mySet = new LinkedHashSet<>();
      for (String str : list) {
          if (mySet.contains(str)) {
              int i = 1;
              while (mySet.contains(str + i)) {
                  i++;
              }
              str = str + i;
          }
          mySet.add(str);
      }
      System.out.println(mySet);
      

      哪些输出(根据要求)

      [a, b, c, d, b1, c1, a1, a2, a3]
      

      【讨论】:

      • @NicolasFilotto List 是不可变的。不确定它在 OP 的情况下是否重要。
      【解决方案4】:

      如果您想对现有列表进行更改:

      public static void main(String ... args) {
          List<String> names = Arrays.asList("a", "b", "c", "d", 
                  "b", "c", "a", "a", "a");
      
          updateDuplicates(names);
      
          System.out.println(names);
      
      }
      
      private static void updateDuplicates(List<String> names) {
          ListIterator<String> litr = names.listIterator();
          Map<String, Integer> occurenceCounter = new HashMap<>();
          while(litr.hasNext()) {
              String currentName = litr.next();
              if(!occurenceCounter.containsKey(currentName)) {
                  occurenceCounter.put(currentName,0);
              }else {
                  Integer currentCount = occurenceCounter.get(currentName);
                  occurenceCounter.put(currentName, ++currentCount);
                  litr.set(currentName + currentCount);
              }
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        您可以将 Java 与散列一起使用 O(n)

        这里l是输入列表

        public static List getUniqueList(List<String> l){
            HashMap<String,Integer> hm=new HashMap<String,Integer>();
            for(int i=0;i<l.size();i++) {
                String key=l.get(i);
                if(hm.containsKey(key)) {
                    l.set(i, key+hm.get(key));
                    hm.put(key,hm.get(key)+1);
                }else { 
                    //newl.add(key);
                    hm.put(key,1);
                }
            }
        return l;
        }
        

        【讨论】:

          猜你喜欢
          • 2019-11-17
          • 2021-07-16
          • 1970-01-01
          • 2016-07-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-30
          相关资源
          最近更新 更多