Повторяющиеся элементы в списке означают элементы, которые встречаются более одного раза.
В этой статье мы рассмотрим различные способы достижения этого, в том числе добавленные в Java 8.

1. Использование набора

Ниже приведен алгоритм этого метода для поиска повторяющихся элементов в списке в java.

  • Создайте новый объект java Set и new arraylist для хранения повторяющихся элементов.
  • Итерация или цикл по списку.
  • Для каждого элемента в списке добавьте его в набор с помощью его метода add().
    add() возвращает true, если элемент добавлен, и false, если элемент уже присутствовал в наборе.
  • Следовательно, если элемент уже есть в Set, то это дубликат.
    Итак, добавляем его в arraylist.
  • В конце итерации повторяющийся список массивов будет содержать все повторяющиеся элементы в исходном списке.

Пример программы, основанной на этом алгоритме, показан ниже.

List<Integer> numbers = List.of(1, 2, 3, 4, 3, 1, 2);
Set<Integer> set = new HashSet<>();
List<Object> duplicates = new ArrayList<>();
numbers.forEach(n -> {
  if (!set.add(n)) {
    duplicates.add(n);
  }
});
System.out.println("Duplicate elements: " + duplicates);

Выход

Duplicate elements: [3, 1, 2]

Обратите внимание, что мы использовали метод java 8 forEach() для перебора списка, но вы также можете использовать любой другой способ.

2. Использование карты

Ниже приведены шаги алгоритма для этого метода.

  • Создайте новый объект карты и новый список массивов для хранения повторяющихся элементов.
    Ключами этой карты будут элементы исходного списка, а ее значениями будет количество их вхождений в список.
  • Прокрутите список.
  • Для каждого элемента в списке проверьте, существует ли он как ключ на карте, используя его метод containsKey().
  • Если он существует, увеличьте его значение на карте и добавьте его снова, используя метод put().
  • Если он не существует, добавьте его на карту со значением 1.
  • После завершения итерации списка все элементы карты со значением больше 1 становятся дубликатами.
  • Наконец, пройтись по карте и добавить те элементы, значение которых больше 1, в список для хранения повторяющихся элементов.

Пример программы, как показано ниже

List<Integer> numbers = List.of(1, 2, 3, 4, 3, 1, 2);
Map<Integer, Integer> countMap = new HashMap<>();
List<Object> duplicates = new ArrayList<>();
numbers.forEach(n -> {
  if (countMap.containsKey(n)) {
    countMap.put(n, countMap.get(n) + 1);
  } else {
    countMap.put(n, 1);
  }
});
countMap.keySet().forEach(k -> {
  if(countMap.get(k)> 1) {
    duplicates.add(k);
  }
});

3. Использование вложенных циклов

Если вас просят найти повторяющиеся элементы в списке без использования каких-либо классов Collection, таких как Set или Map и т. д., то этот метод будет полезен.
Алгоритмические шаги для этого метода:

  • Прокрутите список.
  • Для каждого элемента в списке выполните цикл по остальной части списка.
  • Если текущий элемент цикла равен любому из оставшихся элементов, он является дубликатом.

Программа, написанная в соответствии с этими шагами, выглядит следующим образом

List<Integer> numbers = List.of(1, 2, 3, 4, 3, 1, 2);
List<Object> duplicates = new ArrayList<>();
for (int i = 0; i < numbers.size() - 1; i++) {
  for (int j = i + 1; j < numbers.size(); j++) {
    if (numbers.get(i).equals(numbers.get(j))) {
      duplicates.add(numbers.get(i));
    }
  }
}

4. Использование потоков Java 8

Этот метод основан на потоках Java 8 и работает на следующих шагах.

  • Преобразуйте список в поток.
  • Преобразуйте поток в Map, используя метод collect(), например, ключ — это каждый элемент в списке, а значение — это количество вхождений.
  • Метод collect() возвращает Map и принимает Collector в качестве аргумента. Реализация Collector определяет ключи и значения результирующего Map.
    В этом случае, поскольку мы хотим, чтобы ключи карты были элементами списка, а его значения — количеством их вхождений, мы можем использовать Collectors.groupingBy() для создания коллектор.
  • Как только карта будет создана с помощью groupingBy(), используйте метод entrySet(), чтобы получить набор объектов Map.Entry.
  • Отфильтруйте записи на основе значения (то есть количества вхождений) больше 1.
  • Сопоставьте отфильтрованные записи с их ключами.

Пример программы

List<Integer> numbers = List.of(1, 2, 3, 4, 3, 1, 2);
Map<Object, Long> map = numbers.
                        stream().
                        collect(
                          Collectors.
                          groupingBy(n -> n, Collectors.counting())
                        );
List<Object> duplicates = map.
                          entrySet().
                          stream().
                          filter(e -> e.getValue() > 1).
                          map(e -> e.getKey()).
        collect(Collectors.toList());

groupingBy() используется для группировки элементов коллекции по некоторым критериям.
Вот как работает метод groupingBy() для этого примера:

  • Критерий предоставляется в виде лямбда-выражения, поскольку groupingBy() принимает аргумент Function, который является функциональным интерфейсом.
    В этом случае мы группируем по функции идентификации n -> n, что означает, что мы группируют элементы списка по их значениям.
  • Второй аргумент groupingBy() — это еще один сборщик, указывающий, как должны объединяться элементы в каждой группе.
    В этом случае мы используем Collectors.counting(), который создает Map, содержащий количество каждого элемента в списке.

Таким образом, результирующая карта будет содержать подсчет того, сколько раз каждый элемент появляется в списке.

Затем мы фильтруем эту карту, чтобы найти элементы, количество которых больше 1, что указывает на то, что они являются дубликатами, используя метод filter().

Надеемся, что статья был полезен. Оригинал статьи здесь.