source

Java Array List - 두 목록이 동일한지, 순서는 중요하지 않은지 어떻게 알 수 있습니까?

nicesource 2022. 11. 5. 17:23
반응형

Java Array List - 두 목록이 동일한지, 순서는 중요하지 않은지 어떻게 알 수 있습니까?

는 두 개 요.ArrayList이 s450인 sAnswer( 수 ( (수 )

두 리스트가 같은 내용인지 확인하고 싶은데 순서는 중요하지 않습니다.

예:

//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}

List.equals는 요소의및 .저도 같은 것을 원하지만, 주문은 상관없습니다.

간단한 방법이 있을까요?또는 네스트된 for 루프를 실행하고 두 목록의 각 인덱스를 수동으로 확인해야 합니까?

이 두 수 .ArrayList하다 그들은 그것을 유지해야 합니다.

모든 목록에 대해 가장 쉬운 방법은 다음과 같습니다.

listA.containsAll(listB) && listB.containsAll(listA)

두 목록을 모두 할 수 있습니다.Collections.sort()런음가장 좋은 해결책은 주문하기 전에 길이가 같은지 먼저 확인하고, 그렇지 않은 경우 같지 않은지 확인한 다음 정렬한 다음 동등하게 사용하는 것입니다.현악기 2번

public  boolean equalLists(List<String> one, List<String> two){     
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

Apache Commons Collections를 다시 한 번 구출합니다.

List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true

 

List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false

문서:

org.apache.commons.collections4.CollectionUtils

public static boolean isEqualCollection(java.util.Collection a,
                                        java.util.Collection b)

반품true된 「」의 경우Collections는 정확히 동일한 기수를 가진 정확히 동일한 요소를 포함합니다.

즉, a 또는 b의 각 요소 e에 대해 ae의 카디널리티가 b의 e의 카디널리티와 동일한 경우입니다.

파라미터:

  • a- 첫 번째 컬렉션은 다음과 같을 수 없습니다.null
  • b두은 - 으면 안 요. - 으면 안 돼요.null

반품: true집합이 동일한 기수를 가진 동일한 요소를 포함하는 경우.

// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
    public int count = 0;
}

public boolean haveSameElements(final List<String> list1, final List<String> list2) {
    // (list1, list1) is always true
    if (list1 == list2) return true;

    // If either list is null, or the lengths are not equal, they can't possibly match 
    if (list1 == null || list2 == null || list1.size() != list2.size())
        return false;

    // (switch the two checks above if (null, null) should return false)

    Map<String, Count> counts = new HashMap<>();

    // Count the items in list1
    for (String item : list1) {
        if (!counts.containsKey(item)) counts.put(item, new Count());
        counts.get(item).count += 1;
    }

    // Subtract the count of items in list2
    for (String item : list2) {
        // If the map doesn't contain the item here, then this item wasn't in list1
        if (!counts.containsKey(item)) return false;
        counts.get(item).count -= 1;
    }

    // If any count is nonzero at this point, then the two lists don't match
    for (Map.Entry<String, Count> entry : counts.entrySet()) {
        if (entry.getValue().count != 0) return false;
    }

    return true;
}

이 답변들은 속임수를 놓친 것 같습니다.

Bloch는 그의 필수적이고 훌륭하며 간결한 효과적인 자바에서 항목 47의 제목인 "라이브러리를 알고 사용하라"에서 "요약하면 수레바퀴를 재창조하지 말라"고 말한다.그리고 그는 왜 안되는지 몇 가지 매우 분명한 이유를 제시한다.

에서는 몇 해 주고 있습니다.CollectionUtilsApache Commons Collections 라이브러리에는 있지만 이 질문에 대답할 수 있는 가장 아름답고 우아한 방법을 발견한 사람은 없습니다.

Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
  // ... do something with the culprits, i.e. elements which are not common

}

범인: 즉, 두 가지 모두에 공통적이지 않은 요소Lists이 어떤 list1 을 사용할 것인가?list2를 사용하면 .CollectionUtils.intersection( list1, culprits ) ★★★★★★★★★★★★★★★★★」CollectionUtils.intersection( list2, culprits ).
{ {a}, {a}, {b {b} 등의 이 있습니다.disjunction{a}, {b}, {b}, {b}개 항목...단, 이는 소프트웨어의 장애가 아니라 원하는 태스크의 세부사항/중요성에 기인하는 것입니다.

Apache 엔지니어가 생성한 이러한 작업에 대한 소스 코드(l. 287)를 언제든지 검사할 수 있습니다.코드를 사용함으로써 얻을 수 있는 장점 중 하나는 많은 엣지 케이스와 gotcha가 예상되고 처리되는 철저한 시도와 테스트를 거치게 된다는 것입니다.필요에 따라서, 이 코드를 카피해, 마음껏 조정할 수 있습니다.


나는 에 NB가 도 없다는 했다.CollectionUtils하여 독자적인 를 적용할 수 .Comparator할 수 ).equals★★★★★★★★★★★★★★★★★★★★★」

4.클래스인 "4.0"이 있습니다.Equator「T」 「T」 「 Collection Utils.java 의 소스코드를 몇개의 만, Collection 4 Utils.java사용하는 되지 않습니다.을 사용하다CardinalityHelper★★★★★★★★★★★★★★를 포함한disjunction ★★★★★★★★★★★★★★★★★」intersection

이 않은 하고 있습니다. 「」클래스와 을 만들 이의 「AbstractEquatingCollection」을 사용하는 것이, 「AbstractEquatingCollection」클래스를 만들 필요가 있습니다. 왜냐하면 그것은 사소한 것이 아니기 때문이다: 당신은 그것의 고유한 요소를 사용하는 대신 "AbstractatingEquatingCollection"과 같은 것을 만들어야 할 것이다.equals ★★★★★★★★★★★★★★★★★」hashCode에, 방법에는, 「어느 쪽이 좋을까」라고 하는 합니다.Equator 를 들어,add,contains인 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,AbstractCollection does does does does 。add또, 음, 음, 음, 음, 음, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, sub, subAbstractSet와이 있을 한다.여러분은 다음과 같은 구체적인 수업이 있을 때까지 기다려야 합니다.HashSet ★★★★★★★★★★★★★★★★★」ArrayList 전에add구현되어 있습니다.머리가 많이 아프다.

그러는 동안 이 공간을 지켜봐야 할 것 같다.인 해결책은 모든 를 ' 래퍼' 것입니다.이 클래스는 ''를 사용합니다.equals ★★★★★★★★★★★★★★★★★」hashCode당신이 원하는 종류의 평등을 실현하기 위해...Collections이 래퍼 오브젝트 중 하나입니다.

항목의 카디널리티가 중요하지 않은 경우(즉, 반복된 요소가 하나로 간주됨), 정렬하지 않고도 이를 수행할 수 있는 방법이 있습니다.

boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));

하면 " " " 가 생성됩니다.Set 사람마다List 「」를 합니다.HashSet의 »equals(어느쪽이든)

카디널리티가 중요할 경우 다음에서 제공하는 시설로 제한해야 합니다.List@choenchoen param @ @ @ @ @ @ @ @ @ @ @ @ 。

목록을 Guava의 Multiset으로 변환하는 것은 매우 효과적입니다.순서와 관계없이 비교되며 중복 요소도 고려됩니다.

static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
    return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}

assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));

이는 @cHao 솔루션을 기반으로 합니다.몇 가지 수정사항과 성능 향상을 포함했습니다.이는 주문량이 동일한 복사 솔루션보다 약 2배 더 빠르게 실행됩니다.모든 컬렉션 유형에 대해 작동합니다.빈 컬렉션과 null은 동일한 것으로 간주됩니다.고객에게 유리하게 사용;)

/**
 * Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
 * <p>
 * Empty collections and {@code null} are regarded as equal.
 */
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
    if (col1 == col2)
        return true;

    // If either list is null, return whether the other is empty
    if (col1 == null)
        return col2.isEmpty();
    if (col2 == null)
        return col1.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (col1.size() != col2.size())
        return false;

    // Helper class, so we don't have to do a whole lot of autoboxing
    class Count
    {
        // Initialize as 1, as we would increment it anyway
        public int count = 1;
    }

    final Map<T, Count> counts = new HashMap<>();

    // Count the items in col1
    for (final T item : col1) {
        final Count count = counts.get(item);
        if (count != null)
            count.count++;
        else
            // If the map doesn't contain the item, put a new count
            counts.put(item, new Count());
    }

    // Subtract the count of items in col2
    for (final T item : col2) {
        final Count count = counts.get(item);
        // If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal 
        if (count == null || count.count == 0)
            return false;
        count.count--;
    }

    // At this point, both collections are equal.
    // Both have the same length, and for any counter to be unequal to zero, there would have to be an element in col2 which is not in col1, but this is checked in the second loop, as @holger pointed out.
    return true;
}

컴퓨터나 프로그래밍 언어를 사용하지 않고 직접 이 작업을 수행할 수 있습니다.두 가지 요소 목록을 드릴 테니, 여기에 동일한 요소가 포함되어 있는지 알려주셔야 합니다.그걸 어떻게 하시겠어요?

가지 방법은 위에서한 후 입니다.List.equals알 수 없는 알 수 할당을 모르면 둘 중 하나가 허용되는지 여부를 알 수 없습니다.

다른 방법은 각 요소가 표시되는 횟수를 세어 각 목록을 검토하는 것입니다.양쪽 리스트의 마지막에 같은 카운트가 있는 경우는, 같은 요소가 됩니다.는 각 입니다.elem -> (# of times the elem appears in the list)에 전화해요.equals두 지도에서요.이 「」인 HashMapO(N)가 되다메모리 증설로 시간적으로 매우 효율적인 알고리즘이 실현됩니다.

저도 같은 문제가 있어서 다른 해결책을 생각해 냈어요.이것은 중복이 있는 경우에도 기능합니다.

public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
  if(fst != null && snd != null){
    if(fst.size() == snd.size()){
      // create copied lists so the original list is not modified
      List<?> cfst = new ArrayList<Object>(fst);
      List<?> csnd = new ArrayList<Object>(snd);

      Iterator<?> ifst = cfst.iterator();
      boolean foundEqualObject;
      while( ifst.hasNext() ){
        Iterator<?> isnd = csnd.iterator();
        foundEqualObject = false;
        while( isnd.hasNext() ){
          if( ifst.next().equals(isnd.next()) ){
            ifst.remove();
            isnd.remove();
            foundEqualObject = true;
            break;
          }
        }

        if( !foundEqualObject ){
          // fail early
          break;
        }
      }
      if(cfst.isEmpty()){ //both temporary lists have the same size
        return true;
      }
    }
  }else if( fst == null && snd == null ){
    return true;
  }
  return false;
}

다른 솔루션과 비교한 장점:

  • 복잡도 O(N²) 미만(다른 답변의 솔루션과 비교하여 실제 성능을 테스트하지 않았지만)
  • 조기 종료;
  • null을 확인합니다.
  • 있는 에는 동작합니다.어레이가 있는 경우[1,2,3,3] 배열[1,2,2,3]여기의 대부분의 솔루션은 순서를 고려하지 않을 때 동일하다는 것을 나타냅니다.은 임시 으로써 이를 합니다.
  • 등식을 합니다(의미적 등식).equals가 것)==
  • 않기 별).implement Comparable를 참조해 주세요.

컬렉션을 정렬하지 않고 ["A" "B" "C"]가 [B" "A" "C"와 같지 않은 결과가 필요한 경우,

l1.containsAll(l2)&&l2.containsAll(l1)

충분하지 않습니다.사이즈도 확인해 주세요.

    List<String> l1 =Arrays.asList("A","A","B","C");
    List<String> l2 =Arrays.asList("A","B","C");
    List<String> l3 =Arrays.asList("A","B","C");

    System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
    System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected

    System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
    System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected


    public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
        return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}

Collection Utils 빼기 방법을 활용하는 솔루션:

import static org.apache.commons.collections15.CollectionUtils.subtract;

public class CollectionUtils {
  static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
    if (a == null && b == null)
      return true;
    if (a == null || b == null || a.size() != b.size())
      return false;
    return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
  }
}

순서에 관심이 있는 경우는, 다음과 같은 방법을 사용합니다.

list1.equals(list2)

주문해도 상관없으면 이걸로 해

Collections.sort(list1);
Collections.sort(list2);      
list1.equals(list2)

한 줄 방식:)

  1. 컬렉션의 아이템은 비교 가능 인터페이스를 구현하지 않습니다.< >슈퍼 T>

     static boolean isEqualCollection(Collection<?> a, Collection<?> b) {
         return a == b || (a != null && b != null && a.size() == b.size()
             && a.stream().collect(Collectors.toMap(Function.identity(), s -> 1L, Long::sum)).equals(b.stream().collect(Collectors.toMap(Function.identity(), s -> 1L, Long::sum))));
     }
    
  2. Collection의 아이템은 Comparible 인터페이스를 구현하고 있습니까?슈퍼 T>

     static <T extends Comparable<? super T>> boolean  isEqualCollection2(Collection<T> a, Collection<T> b) {
       return a == b || (a != null && b != null && a.size() == b.size() && a.stream().sorted().collect(Collectors.toList()).equals(b.stream().sorted().collect(Collectors.toList())));
     }
    
  3. https://github.com/retrostreams/android-retrostreams에서 Android5 및 Android6 지원

    static boolean isEqualCollection(Collection<?> a, Collection<?> b) {
     return a == b || (a != null && b != null && a.size() == b.size()
             && StreamSupport.stream(a).collect(Collectors.toMap(Function.identity(), s->1L, Longs::sum)).equals(StreamSupport.stream(b).collect(Collectors.toMap(Function.identity(), s->1L, Longs::sum))));
    }
    

////테스트 케이스

    boolean isEquals1 = isEqualCollection(null, null); //true
    boolean isEquals2 = isEqualCollection(null, Arrays.asList("1", "2")); //false
    boolean isEquals3 = isEqualCollection(Arrays.asList("1", "2"), null); //false
    boolean isEquals4 = isEqualCollection(Arrays.asList("1", "2", "2"), Arrays.asList("1", "1", "2")); //false
    boolean isEquals5 = isEqualCollection(Arrays.asList("1", "2"), Arrays.asList("2", "1")); //true
    boolean isEquals6 = isEqualCollection(Arrays.asList("1", 2.0), Arrays.asList(2.0, "1")); //true
    boolean isEquals7 = isEqualCollection(Arrays.asList("1", 2.0, 100L), Arrays.asList(2.0, 100L, "1")); //true
    boolean isEquals8 = isEqualCollection(Arrays.asList("1", null, 2.0, 100L), Arrays.asList(2.0, null, 100L, "1")); //true

양쪽의 장점 [@DiddiZ, @Chalkos] : 이것은 주로 @Chalkos 메서드를 기반으로 구축되지만 버그(ifst.next)를 수정하고 초기 체크(@DiddiZ에서 취득)를 개선하며 첫 번째 컬렉션을 복사할 필요가 없어집니다(두 번째 컬렉션의 복사본에서 항목을 삭제합니다).

해시함수나 정렬이 필요하지 않고 불균등하게 조기실현을 가능하게 하는 것은 지금까지 구현된 것 중 가장 효율적인 구현입니다.수천 개 이상의 수집 길이와 매우 단순한 해싱 함수가 없는 경우입니다.

public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
    if (one == two)
        return true;

    // If either list is null, return whether the other is empty
    if (one == null)
        return two.isEmpty();
    if (two == null)
        return one.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (one.size() != two.size())
        return false;

    // copy the second list, so it can be modified
    final List<T> ctwo = new ArrayList<>(two);

    for (T itm : one) {
        Iterator<T> it = ctwo.iterator();
        boolean gotEq = false;
        while (it.hasNext()) {
            if (itm.equals(it.next())) {
                it.remove();
                gotEq = true;
                break;
            }
        }
        if (!gotEq) return false;
    }
    // All elements in one were found in two, and they're the same size.
    return true;
}

이는 null 값을 포함할 수 있는 배열 목록의 동일성을 확인하는 대체 방법입니다.

List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);

System.out.println(checkEquality(listA, listB)); // will return TRUE


private List<String> getSortedArrayList(List<String> arrayList)
{
    String[] array = arrayList.toArray(new String[arrayList.size()]);

    Arrays.sort(array, new Comparator<String>()
    {
        @Override
        public int compare(String o1, String o2)
        {
            if (o1 == null && o2 == null)
            {
                return 0;
            }
            if (o1 == null)
            {
                return 1;
            }
            if (o2 == null)
            {
                return -1;
            }
            return o1.compareTo(o2);
        }
    });

    return new ArrayList(Arrays.asList(array));
}

private Boolean checkEquality(List<String> listA, List<String> listB)
{
    listA = getSortedArrayList(listA);
    listB = getSortedArrayList(listB);

    String[] arrayA = listA.toArray(new String[listA.size()]);
    String[] arrayB = listB.toArray(new String[listB.size()]);

    return Arrays.deepEquals(arrayA, arrayB);
}

이 문제에 대한 나의 해결책.그것은 그렇게 멋지지는 않지만 잘 작동한다.

public static boolean isEqualCollection(List<?> a, List<?> b) {

    if (a == null || b == null) {
        throw new NullPointerException("The list a and b must be not null.");
    }

    if (a.size() != b.size()) {
        return false;
    }

    List<?> bCopy = new ArrayList<Object>(b);

    for (int i = 0; i < a.size(); i++) {

        for (int j = 0; j < bCopy.size(); j++) {
            if (a.get(i).equals(bCopy.get(j))) {
                bCopy.remove(j);
                break;
            }
        }
    }

    return bCopy.isEmpty();
}

이 경우 목록 {"a", "b"} 및 {"b", "a"}이(가) 동일합니다.그리고 {"a", "b"}와 {"b", "a", "c"}는 같지 않습니다.복잡한 개체 목록을 사용하는 경우 다음과 같이 equals 메서드를 재정의해야 합니다.모두 안에서 사용합니다.

if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
        areEqual = true;
}

언급URL : https://stackoverflow.com/questions/13501142/java-arraylist-how-can-i-tell-if-two-lists-are-equal-order-not-mattering

반응형