2016-11-26 2 views
8

У меня есть 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

Почему вы хранить данные в списке массива? Это точка начала. –

+0

@ThomasJunk. Мне нужен список с повторяющимися значениями. Там в любом случае? – user2196474

ответ

9

Похоже, у вас есть правильная идея. Вам просто нужно использовать 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); 
    } 
} 
7

Предполагая, что вы используете 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 Фриша.

немного другой подход от Elliott Фриша «ы один:

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] 
4

Вы можете использовать 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] 
+0

@NicolasFilotto Этот 'List' не изменчив. Не уверен, имеет ли это значение в случае OP. –

Смежные вопросы