목록에서 중복 식별


120

예를 들어 정수 유형의 목록이 있습니다.

[1, 1, 2, 3, 3, 3]

예를 들어 모든 중복을 반환하는 방법을 원합니다.

[1, 3]

이를 수행하는 가장 좋은 방법은 무엇입니까?


2
입력 목록이 정렬되도록 보장됩니까 (예시와 같이)?
NPE 2011 년

7
목록을 정렬 한 다음 현재 값과 이전 값을 유지하면서 살펴보세요. 현재 == 이전이면 중복이 있습니다.
mcfinnigan

아니요, 목록이 반드시 정렬 된 것은 아닙니다.
가장 신선한 '

답변:


183

의 메서드 addSet값이 이미 존재하는지 여부를 부울 로 반환합니다 (존재하지 않으면 true, 이미 존재하면 false, Set documentation 참조 ).

따라서 모든 값을 반복하십시오.

public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{ 
  final Set<Integer> setToReturn = new HashSet<>(); 
  final Set<Integer> set1 = new HashSet<>();

  for (Integer yourInt : listContainingDuplicates)
  {
   if (!set1.add(yourInt))
   {
    setToReturn.add(yourInt);
   }
  }
  return setToReturn;
}

1
왜 setToReturn을 사용합니까? set1.add (yourInt)를 사용하고 set1을 반환 할 수 없습니까?

3
맞아요. 그러나 elemnt가 지정된 목록에 한 번만 있으면 요소도 추가됩니다. 질문의 예를보십시오. 내 솔루션은 숫자 2가 set1에 삽입되었지만 setToReturn에는 삽입되지 않았으므로 [1,3]을 반환합니다. 솔루션은 [1,2,3]을 반환합니다 (요구 사항이 아님)
leifg

1
for (Integer yourInt특히 입력에 이미 Integers 가 포함되어 있기 때문에 불필요한 boxing 및 unboxing을 피하기 위해 를 사용하는 것이 좋습니다 .
Hosam Aly 2011 년

1
@JonasThelemann 세트의 전체 아이디어는 중복을 포함 할 수 없다는 것입니다. 따라서 : 3을 얼마나 자주 추가하든 상관없이 항상 한 번만 끝납니다.
leifg

1
그건 그렇고, HashSet부하 계수도 고려해야하는 경우, 예를 들어 초기 용량을 지정할 때 100요소 수를 추가하려는 경우 다음 거듭 제곱 2 ( 128)로 반올림됩니다. 기본로드 비율이 0.75f인 경우 크기 조정 임계 값은입니다 96. 따라서 100요소를 추가하기 전에 크기가 조정됩니다 . 고맙게도 크기 조정은 더 이상 비싸지 않습니다. 최신 JRE를 사용하면 크기 조정이 더 이상 재해시되지 않으며 요소는 관련 비트를 기반으로 두 가능한 결과 위치 사이에 분산됩니다.
Holger

50

이것에 대한 해결책도 필요했습니다. 나는 leifg의 솔루션을 사용하여 일반화했습니다.

private <T> Set<T> findDuplicates(Collection<T> collection) {

    Set<T> duplicates = new LinkedHashSet<>();
    Set<T> uniques = new HashSet<>();

    for(T t : collection) {
        if(!uniques.add(t)) {
            duplicates.add(t);
        }
    }

    return duplicates;
}

1
나는 이것이 3 년 후라는 것을 알고 있지만, LinkedHashedSet이 왜 필요한지, 즉 주문에 대해 왜 관심이 있습니까?
Ahmad Ragab 2016

4
@AhmadRagab 맞아요, LinkedHashSet는 중복이 발견 된 순서에 신경 쓰지 않는 한 필요하지 않습니다 (제가 당시에했던 것 같습니다)
John Strickler

팔로우 해 주셔서 감사합니다!
Ahmad Ragab 2016

입력 데이터가 너무 많아서 입력을 정렬하는 대신이 최적의 솔루션을 사용하려는 경우 HashSet () 개체의 크기도 미리 할당 할 수 있습니다. 사전 할당이 없으면 HashSet ()에 삽입 할 때 O (1) 삽입 시간을 얻지 못합니다. 내부 해시 배열의 크기가 반복적으로 조정되기 때문입니다. 그런 다음 삽입은 O (log N) 시간과 같은 평균을냅니다. 이는 모든 N 항목을 처리하는 것이 O (N) 일 수있을 때 O (N log N)가됨을 의미합니다.
johnstosh

39

John Strickler의 솔루션을 가져와 JDK8에 도입 된 스트림 API를 사용하도록 다시 만들었습니다.

private <T> Set<T> findDuplicates(Collection<T> collection) {
    Set<T> uniques = new HashSet<>();
    return collection.stream()
        .filter(e -> !uniques.add(e))
        .collect(Collectors.toSet());
}

3
읽기가 좀 어렵 네요. 스트림 작업에서 부작용을 일으켜 추론하기가 어렵습니다. 그러나 그것은 기능적인 스타일을 생각하는 나뿐입니다. 간결하고 아마도 가장 짧은 방법입니다.).
froginvasion

큰 목록의 경우 여러 스레드에서 병렬로 실행할 수 있습니까?
johnstosh

@froginvasion 내장 distinct()메소드도 상태 저장입니다. 상태 저장이 아닌 효율적인 (O (n)) 별개의 작업을 생각할 수 없습니다.
wilmol

18

다음은 Java 8과 함께 Streams를 사용하는 솔루션입니다.

// lets assume the original list is filled with {1,1,2,3,6,3,8,7}
List<String> original = new ArrayList<>();
List<String> result = new ArrayList<>();

이 개체의 빈도가 목록에서 두 번 이상인지 확인합니다. 그런 다음 .distinct ()를 호출하여 결과에 고유 한 요소 만 포함합니다.

result = original.stream()
    .filter(e -> Collections.frequency(original, e) > 1)
    .distinct()
    .collect(Collectors.toList());
// returns {1,3}
// returns only numbers which occur more than once

result = original.stream()
    .filter(e -> Collections.frequency(original, e) == 1)
    .collect(Collectors.toList());
// returns {2,6,8,7}
// returns numbers which occur only once

result = original.stream()
    .distinct()
    .collect(Collectors.toList());
// returns {1,2,3,6,8,7}
// returns the list without duplicates

1
이것은 가독성 측면에서 좋지만 성능 에는 정말 나쁩니다. Collections::frequencyO (n)입니다. 항목의 빈도를 찾으려면 전체 컬렉션을 살펴 봐야합니다. 그리고 우리는 컬렉션의 모든 항목에 대해 이것을 한 번 호출하여 이러한 스 니펫을 만듭니다 O(n^2). 소수 이상의 요소 모음에서 차이를 알 수 있습니다. 나는 이것을 실제 코드에서 사용하지 않을 것입니다.
Pawan

13

자바 8 기본 솔루션 :

List duplicates =    
list.stream().collect(Collectors.groupingBy(Function.identity()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

입력 목록은 맵으로 변환됩니다 (동일한 값으로 그룹화). 다음 고유 한 값지도의 값은 "삭제"하는 다음 키를 사용하여지도, 다음 목록의 목록은 목록에 변환
بلال المصمودي

항목의 특정 게터에 대한 필터링으로 직접 수정 가능한 아름답고 빠른 솔루션
arberg

11
int[] nums =  new int[] {1, 1, 2, 3, 3, 3};
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {

    if (nums[i] == nums[i+1]) {
        System.out.println("duplicate item "+nums[i+1]+" at Location"+(i+1) );
    }

}

분명히 인쇄하는 대신 원하는 모든 작업을 수행 할 수 있습니다 (즉, 중복 값의 고유 한 목록을 얻기 위해 Set에 넣음). 이것은 또한 중복 항목의 위치를 ​​기록하는 이점도 있습니다.


7

Java 8에서 Guava 사용

private Set<Integer> findDuplicates(List<Integer> input) {
    // Linked* preserves insertion order so the returned Sets iteration order is somewhat like the original list
    LinkedHashMultiset<Integer> duplicates = LinkedHashMultiset.create(input);

    // Remove all entries with a count of 1
    duplicates.entrySet().removeIf(entry -> entry.getCount() == 1);

    return duplicates.elementSet();
}

7

이것은 또한 작동합니다 :

public static Set<Integer> findDuplicates(List<Integer> input) {
    List<Integer> copy = new ArrayList<Integer>(input);
    for (Integer value : new HashSet<Integer>(input)) {
        copy.remove(value);
    }
    return new HashSet<Integer>(copy);
}

작동하지만 배열 목록에서 remove ()를 호출하는 것은 선형 검색이므로 다소 느립니다.
johnstosh

진실. 입력에 중복 항목이 많이 포함되어 있으면 중복 항목이 몇 개만있는 경우보다 성능 저하가 적습니다.
Adriaan Koster

6

다음과 같이 사용할 수 있습니다.

List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
    yourOldList.remove(i);
    if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}

2
여기서 List를 사용하는 것은 매우 비효율적입니다
Alexander Farber 2011 년

2
그리고 int여기서 변수 유형 으로 사용하기 시작하지 마십시오 . 이는 매 반복마다 Integer가 한 번 박스 해제되고 int가 네 번 박스됨을 의미합니다!
Sean Patrick Floyd

1
그것을 반복하면서 목록에서 요소를 제거하려고 할 때 당신이 쉽게 ConcurrentModificationException를 얻을 수 있다고 생각
이 ì B를

1
목록을 반복하고 즉시 요소를 제거하기 때문에 이것은 100 % ConcurrentModificationException입니다.
theo231022

5

Lambas는 해결책이 될 수 있습니다

Integer[] nums =  new Integer[] {1, 1, 2, 3, 3, 3};
List<Integer> list = Arrays.asList(nums);

List<Integer> dps = list.stream().distinct().filter(entry -> Collections.frequency(list, entry) > 1).collect(Collectors.toList());

1
작동하지만 각 항목에 대해 Collections.frequency를 실행하므로 느립니다.
arberg

4

MultiMap을 사용하여 각 값을 키 / 값 집합으로 저장합니다. 그런 다음 키를 반복하고 여러 값이있는 키를 찾습니다.


3

Eclipse Collections 를 사용하면 다음 과 같이 작동합니다.

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectByOccurrences(i -> i > 1).toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

업데이트 : Eclipse Collections 9.2부터 이제 사용할 수 있습니다.selectDuplicates

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

기본 컬렉션을 사용하여이를 수행 할 수도 있습니다.

IntList list = IntLists.mutable.with(1, 1, 2, 3, 3, 3);
IntSet dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(IntSets.mutable.with(1, 3), dupes);

참고 : 저는 Eclipse Collections의 커미터입니다.


2
public class practicese {
       public static void main(String[] args) {   

           List<Integer> listOf = new ArrayList<Integer>();
           listOf.add(3);
           listOf.add(1);
           listOf.add(2);
           listOf.add(3);
           listOf.add(3);
           listOf.add(2);
           listOf.add(1);

           List<Integer> tempList = new ArrayList<Integer>();
           for(Integer obj:listOf){
                if(!tempList.contains(obj)){
                    tempList.add(obj);

                }
            }
            System.out.println(tempList);

    }

}

나는이 답변이 마음에 들었고 다른 목록에 중복을 저장하기 위해 다른 것을 추가해야했습니다. 감사합니다
Tiago Machado

2

여기의 일부 답변과 유사하지만 일부 속성을 기반으로 중복을 찾으려면 다음을 수행하십시오.

  public static <T, R> Set<R> findDuplicates(Collection<? extends T> collection, Function<? super T, ? extends R> mapper) {
    Set<R> uniques = new HashSet<>();
    return collection.stream()
        .map(mapper)
        .filter(e -> !uniques.add(e))
        .collect(toSet());
  }

1

를 만들고 Map<Integer,Integer>목록을 반복하고, 요소가지도에 있으면 값을 늘리고, 그렇지 않으면 key = 1
로지도에 추가하고,지도를 반복하고, key> = 2로 모든 요소를 ​​목록에 추가합니다.

public static void main(String[] args) {
        List<Integer> list = new LinkedList<Integer>();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(3);
        Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        for (Integer x : list) { 
            Integer val = map.get(x);
            if (val == null) { 
                map.put(x,1);
            } else {
                map.remove(x);
                map.put(x,val+1);
            }
        }
        List<Integer> result = new LinkedList<Integer>();
        for (Entry<Integer, Integer> entry : map.entrySet()) {
            if (entry.getValue() > 1) {
                result.add(entry.getKey());
            }
        }
        for (Integer x : result) { 
            System.out.println(x);
        }

    }

이것은 꽤 좋습니다. 얼마나 많은 중복이 있었는지 알아야 할 때 가장 좋은 솔루션입니다. 참고 사항 : (1) put ()을 수행하기 전에 remove ()를 호출 할 필요가 없습니다. (2) 반복되는 add () 호출을 사용하지 않고 배열에서 LinkedList를 설정할 수 있습니다. (3) val! = null이면 즉시 결과에 x를 추가 할 수 있습니다. 결과는 중복 수를 유지 하려는지 여부에 따라 세트 또는 목록이 될 수 있습니다.
johnstosh

1

상위 답변의 컴팩트 생성 버전, 빈 확인 및 사전 할당 된 세트 크기 추가 :

public static final <T> Set<T> findDuplicates(final List<T> listWhichMayHaveDuplicates) {
    final Set<T> duplicates = new HashSet<>();
    final int listSize = listWhichMayHaveDuplicates.size();
    if (listSize > 0) {
      final Set<T> tempSet = new HashSet<>(listSize);
      for (final T element : listWhichMayHaveDuplicates) {
        if (!tempSet.add(element)) {
          duplicates.add(element);
        }
      }
    }
    return duplicates;
  }

제로 체크가 필요합니까? new HashSet <> (0)은 합리적인 빈 세트를 반환합니까?
johnstosh

@johnstosh이 코드는 단순화 될 수 있지만 0을 확인 하면 필요할 때만 tempSetwith를 초기화 listSize할 수 있습니다. 이것은 사소한 최적화이지만 나는 그것을 좋아합니다.
Christophe Roussy

1

Sebastian의 대답을 받아 keyExtractor를 추가했습니다.

    private <U, T> Set<T> findDuplicates(Collection<T> collection, Function<? super T,? extends U> keyExtractor) {
        Map<U, T> uniques = new HashMap<>(); // maps unique keys to corresponding values
        return collection.stream()
            .filter(e -> uniques.put(keyExtractor.apply(e), e) != null)
            .collect(Collectors.toSet());
    }

1

스레드로부터 안전한 대안은 다음과 같습니다.

/**
 * Returns all duplicates that are in the list as a new {@link Set} thread-safe.
 * <p>
 * Usually the Set will contain only the last duplicate, however the decision
 * what elements are equal depends on the implementation of the {@link List}. An
 * exotic implementation of {@link List} might decide two elements are "equal",
 * in this case multiple duplicates might be returned.
 * 
 * @param <X>  The type of element to compare.
 * @param list The list that contains the elements, never <code>null</code>.
 * @return A set of all duplicates in the list. Returns only the last duplicate.
 */
public <X extends Object> Set<X> findDuplicates(List<X> list) {
    Set<X> dups = new LinkedHashSet<>(list.size());
    synchronized (list) {
        for (X x : list) {
            if (list.indexOf(x) != list.lastIndexOf(x)) {
                dups.add(x);
            }
        }
    }
    return dups;
}

0

목록에서 중복 항목을 찾으려면 다음을 시도하십시오.

ArrayList<String> arrayList1 = new ArrayList<String>(); 

arrayList1.add("A"); 
arrayList1.add("A"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("C"); 

for (int x=0; x< arrayList1.size(); x++) 
{ 
System.out.println("arrayList1 :"+arrayList1.get(x)); 
} 
Set s=new TreeSet(); 
s.addAll(arrayList1); 
Iterator it=s.iterator(); 
while (it.hasNext()) 
{ 
System.out.println("Set :"+(String)it.next()); 
} 

예, 이것은 세트를 찾지 만 중복 된 항목의 목록이나 세트를 찾지 않습니다.
johnstosh

0

이것은 정렬 및 정렬되지 않은 경우에 작동합니다.

public void testFindDuplicates() {

    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(3);
    list.add(3);

    Set<Integer> result = new HashSet<Integer>();
    int currentIndex = 0;
    for (Integer i : list) {
        if (!result.contains(i) && list.subList(currentIndex + 1, list.size()).contains(i)) {
            result.add(i);
        }
        currentIndex++;
    }
    assertEquals(2, result.size());
    assertTrue(result.contains(1));
    assertTrue(result.contains(3));
}

ArrayList의 subList에서 contains ()를 호출하는 것은 선형 검색이기 때문에 비용이 많이 듭니다. 따라서 이것은 10 개 항목에 대해서는 괜찮지 만 1000 만개는 아닙니다.
johnstosh

0

이것은 기능적 기술이 빛나는 문제입니다. 예를 들어, 다음 F # 솔루션은 최고의 명령형 Java 솔루션보다 명확하고 버그가 적습니다 (저는 Java와 F # 모두에서 매일 작업합니다).

[1;1;2;3;3;3] 
|> Seq.countBy id 
|> Seq.choose (fun (key,count) -> if count > 1 then Some(key) else None)

물론이 질문은 자바에 관한 것입니다. 그래서 제 제안은 Java에 기능적 기능을 제공하는 라이브러리를 채택하는 것입니다. 예를 들어 다음과 같이 내 라이브러리 를 사용하여 해결할 수 있습니다 (그리고 살펴볼 가치가있는 다른 라이브러리 도 있습니다).

Seq.of(1,1,2,3,3,3)
.groupBy(new Func1<Integer,Integer>() {
    public Integer call(Integer key) {
        return key;
    }
}).filter(new Predicate<Grouping<Integer,Integer>>() {
   public Boolean call(Grouping<Integer, Integer> grouping) {
        return grouping.getGrouping().count() > 1;
   }
}).map(new Func1<Grouping<Integer,Integer>,Integer>() {
    public Integer call(Grouping<Integer, Integer> grouping) {
        return grouping.getKey();
    }
});

그리고 자바가 실제로 함수형 프로그래밍에서 얼마나 짜증나는지 알 수 있습니다. 이러한 간단한 문제는 Java에서 원하는 것을 표현하기가 너무 어렵습니다.
froginvasion

0
public class DuplicatesWithOutCollection {

    public static void main(String[] args) {

        int[] arr = new int[] { 2, 3, 4, 6, 6, 8, 10, 10, 10, 11, 12, 12 };

        boolean flag = false;
        int k = 1;
        while (k == 1) {

            arr = removeDuplicate(arr);
            flag = checkDuplicate(arr, flag);
            if (flag) {
                k = 1;
            } else {
                k = 0;
            }

        }

    }

    private static boolean checkDuplicate(int[] arr, boolean flag) {
        int i = 0;

        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                flag = true;

            } else {
                flag = false;
            }
            i++;

        }

        return flag;
    }

    private static int[] removeDuplicate(int[] arr) {

        int i = 0, j = 0;
        int[] temp = new int[arr.length];
        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                temp[j] = arr[i + 1];
                i = i + 2;

            } else {

                temp[j] = arr[i];
                i = i + 1;

                if (i == arr.length - 1) {
                    temp[j + 1] = arr[i + 1];
                    break;
                }

            }
            j++;

        }
        System.out.println();
        return temp;
    }

}

Collection 클래스를 사용하지 않고 구현. 그러나 루프에서 약간의 개선이 필요합니다. 자원 봉사 도움이 감사합니다. 위의 결과는 다음과 같습니다 .--> 2 34 6 8 10 11 12
Samrat Roy

이 작업을 더 짧은 시간에 실행하려면 해시 기반 데이터 구조를 사용하여 중복을 추적해야합니다. 그렇기 때문에 HashSet ()을 사용하는 다른 솔루션을 볼 수 있습니다. Java에 내장되어 있습니다.
johnstosh

@johnstosh 예, 알고 있지만 컬렉션을 사용하지 않고 만들려고 생각하고 있었기 때문에 내 의견에 언급했습니다. 보시다시피 2017 년 2 월 이전에 댓글을 달았습니다. [컬렉션을 전혀 사용할 필요가없는 기술이 있습니다. 더 적은 시간 복잡성으로] geeksforgeeks.org/… . 나는 DS & Algo 관행을 알지 못한 채 그 프로그램을 시도했습니다. 당신은 그것을 위해 저를 비판 할 필요가 없습니다 .. 어쨌든 감사합니다.
Samrat Roy

0
import java.util.Scanner;

public class OnlyDuplicates {
    public static void main(String[] args) {
        System.out.print(" Enter a set of 10 numbers: ");
        int[] numbers = new int[10];
        Scanner input = new Scanner(System.in);
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = input.nextInt();
        }
        numbers = onlyDuplicates(numbers);
        System.out.print(" The numbers are: ");
        for (int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + "");
        }
    }

    public static int[] onlyDuplicates(int[] list) {
        boolean flag = true;
        int[] array = new int[0];
        array = add2Array(array, list[0]);
        for (int i = 0; i < list.length; i++) {
            for (int j = 0; j < array.length; j++) {
                if (list[i] == array[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                array = add2Array(array, list[i]);
            }
            flag = true;
        }
        return array;
    }
    // Copy numbers1 to numbers2
    // If the length of numbers2 is less then numbers2, return false
    public static boolean copyArray(int[] source, int[] dest) {
        if (source.length > dest.length) {
            return false;
        }

        for (int i = 0; i < source.length; i++) {
            dest[i] = source[i];
        }
        return true;
    }
    // Increase array size by one and add integer to the end of the array
    public static int[] add2Array(int[] source, int data) {
        int[] dest = new int[source.length + 1];
        copyArray(source, dest);
        dest[source.length] = data;
        return dest;
    }
}

중복을 반환하려면 무엇을 변경해야합니까?
Brenden

이것은 새로운 질문으로해야합니다.
willaien 17.11.17

0

이것은 Set을 사용하지 않고 중복 값을 찾는 좋은 방법입니다.

public static <T> List<T> findDuplicates(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();

  for(T s : list)
    if(list.indexOf(s) != list.lastIndexOf(s))
      if(!nonDistinctElements.contains(s))
        nonDistinctElements.add(s);

  return nonDistinctElements;
}

예를 들어, 요소가 두 번 이상 발생하는 목록을 전달하면 고유 한 요소가 포함 된 목록을 얻을 수 있습니다.

public static <T> void distinctList(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();
for(T s : list)
  if(list.indexOf(s) != list.lastIndexOf(s))
    nonDistinctElements.add(s);

for(T nonDistinctElement : nonDistinctElements)
  if(list.indexOf(nonDistinctElement) != list.lastIndexOf(nonDistinctElement))
    list.remove(nonDistinctElement);
}

0

그리고 commons-collections CollectionUtils.getCardinalityMap방법 을 사용 하는 버전 :

final List<Integer> values = Arrays.asList(1, 1, 2, 3, 3, 3);
final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(values);
System.out.println(cardinalityMap
            .entrySet()
            .stream().filter(e -> e.getValue() > 1)
            .map(e -> e.getKey())
            .collect(Collectors.toList()));

```


0

이 코드는 어떻습니까?

public static void main(String[] args) {

    //Lets say we have a elements in array
    int[] a = {13,65,13,67,88,65,88,23,65,88,92};

    List<Integer> ls1 = new ArrayList<>();
    List<Integer> ls2 = new ArrayList<>();
    Set<Integer> ls3 = new TreeSet<>();

    //Adding each element of the array in the list      
    for(int i=0;i<a.length;i++) {
     {
    ls1.add(a[i]);
    }
    }

    //Iterating each element in the arrary
    for (Integer eachInt : ls1) {

    //If the list2 contains the iterating element, then add that into set<> (as this would be a duplicate element)
        if(ls2.contains(eachInt)) {
            ls3.add(eachInt);
        }
        else {ls2.add(eachInt);}

    }

    System.out.println("Elements in array or ls1"+ls1); 
    System.out.println("Duplicate Elements in Set ls3"+ls3);


}

0

중복 및 비 중복을 모두 포함하려는 경우에만 해당됩니다. 기본적으로 정답과 비슷하지만 부분이 아닌 경우 반환하는 대신 else 부분을 반환합니다.

이 코드 사용 (필요한 유형으로 변경)

public Set<String> findDup(List<String> Duplicates){
    Set<String> returning = new HashSet<>();
    Set<String> nonreturning = new HashSet<>();
    Set<String> setup = new HashSet<>();
    for(String i:Duplicates){
        if(!setup.add( i )){
            returning.add( i );
        }else{
            nonreturning.add( i );
        }
    }
    Toast.makeText( context,"hello set"+returning+nonreturning+" size"+nonreturning.size(),Toast.LENGTH_SHORT ).show();
    return nonreturning;
}

0

https://stackoverflow.com/a/52296246의 변형으로 더 일반적인 방법

    /**
     * Returns a duplicated values found in given collection based on fieldClassifier
     *
     * @param collection given collection of elements
     * @param fieldClassifier field classifier which specifies element to check for duplicates(useful in complex objects).
     * @param <T> Type of element in collection
     * @param <K> Element which will be returned from method in fieldClassifier.
     * @return returns list of values that are duplocated.
     */
    public static <T, K> List<K> lookForDuplicates(List<T> collection, Function<? super T, ? extends K> fieldClassifier) {

        return collection.stream().collect(Collectors.groupingBy(fieldClassifier))
                         .entrySet()
                         .stream()
                         .filter(e -> e.getValue().size() > 1)
                         .map(Map.Entry::getKey)
                         .collect(Collectors.toList());
    }

-1

최대 값 (예 : <10000)을 알고 있다면 속도를 위해 공간을 희생 할 수 있습니다. 이 기술의 정확한 이름을 기억할 수 없습니다.

의사 코드 :

//does not handle case when mem allocation fails 
//probably can be extended to unknown values /larger values .
maybe by sorting first
public List<int> GetDuplicates(int max)
{   
    //allocate and clear memory to 0/false
    bit[] buckets=new bit[max]
    memcpy(buckets,0,max);
    //find duplicates
    List<int> result=new List<int>();
    foreach(int val in List)
    {
        if (buckets[val])
        {
            result.add(value);
        }
        else
        {
            buckets[val]=1;
        }
    }
    return  result
}

"비트"대신 "부울"을 원하십니까? 코드를 게시하기 전에 실행 했습니까? 이것은 좋은 시작입니다. HashSet ()를 살펴보면 원하는 '버킷'구현임을 알 수 있습니다.
johnstosh

-1

이것을 시도하십시오 :

목록 값이 [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] 중복 항목 [3, 4] 인 경우의 예입니다.

Collections.sort(list);
        List<Integer> dup = new ArrayList<>();
        for (int i = 0; i < list.size() - 1; i++) {
            if (list.get(i) == list.get(i + 1)) {
                if (!dup.contains(list.get(i + 1))) {
                    dup.add(list.get(i + 1));
                }
            }
        }
        System.out.println("duplicate item " + dup);

ArrayList ()에서 contains ()를 호출하는 것은 비용이 많이 드는 작업이므로 대신 Set 사용을 고려해야합니다. HashSet () 또는 링크 된 버전을 사용하는 다른 솔루션을 볼 수 있습니다.
johnstosh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.