在列表中查找重复的字符串并使它们唯一化

11

我有一个包含重复字符串值的 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

2
你为什么要将数据存储在数组列表中?这本来就是开始的重点。 - Thomas Junk
@ThomasJunk。我想要包含重复值的列表。有什么办法吗? - user2196474
5个回答

14
假设您使用的是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]

11

似乎你的想法是正确的。你只需要使用一个 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);
    }
}

5
你可以使用 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 的情况下是否重要。 - Elliott Frisch

2

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

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);
        }
    }

}

1
你可以使用哈希表和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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接