[java] Java에서 ArrayList의 교차 및 결합

그렇게하는 방법이 있습니까? 찾고 있었지만 찾을 수 없었습니다.

또 다른 질문 : 파일을 필터링 할 수 있도록 이러한 방법이 필요합니다. 일부는 AND필터이고 일부는 OR(이론과 같은) 필터이므로 모든 파일에 따라 필터링해야하며 해당 파일을 보유하는 Unite / intersects ArrayList를 필터링해야합니다.

파일을 보유하기 위해 다른 데이터 구조를 사용해야합니까? 더 나은 런타임을 제공하는 다른 것이 있습니까?



답변

다음은 타사 라이브러리를 사용하지 않는 일반 구현입니다. 주요 장점을 통해 retainAll, removeAll그리고 addAll이러한 방법은 방법 원래 목록 입력을 수정하지 않는 것이 있습니다.

public class Test {

    public static void main(String... args) throws Exception {

        List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C"));
        List<String> list2 = new ArrayList<String>(Arrays.asList("B", "C", "D", "E", "F"));

        System.out.println(new Test().intersection(list1, list2));
        System.out.println(new Test().union(list1, list2));
    }

    public <T> List<T> union(List<T> list1, List<T> list2) {
        Set<T> set = new HashSet<T>();

        set.addAll(list1);
        set.addAll(list2);

        return new ArrayList<T>(set);
    }

    public <T> List<T> intersection(List<T> list1, List<T> list2) {
        List<T> list = new ArrayList<T>();

        for (T t : list1) {
            if(list2.contains(t)) {
                list.add(t);
            }
        }

        return list;
    }
}


답변

컬렉션 (따라서 ArrayList도)은 다음과 같습니다.

col.retainAll(otherCol) // for intersection
col.addAll(otherCol) // for union

반복을 수락하면 List 구현을 사용하고, 그렇지 않으면 Set 구현을 사용하십시오.

Collection<String> col1 = new ArrayList<String>(); // {a, b, c}
// Collection<String> col1 = new TreeSet<String>();
col1.add("a");
col1.add("b");
col1.add("c");

Collection<String> col2 = new ArrayList<String>(); // {b, c, d, e}
// Collection<String> col2 = new TreeSet<String>();
col2.add("b");
col2.add("c");
col2.add("d");
col2.add("e");

col1.addAll(col2);
System.out.println(col1);
//output for ArrayList: [a, b, c, b, c, d, e]
//output for TreeSet: [a, b, c, d, e]


답변

이 게시물은 상당히 오래되었지만 그럼에도 불구하고 해당 주제를 찾을 때 Google에 처음 나타나는 게시물입니다.

Java 8 스트림을 사용하여 한 줄에 (기본적으로) 동일한 작업을 수행하여 업데이트를 제공하고 싶습니다.

List<T> intersect = list1.stream()
    .filter(list2::contains)
    .collect(Collectors.toList());

List<T> union = Stream.concat(list1.stream(), list2.stream())
    .distinct()
    .collect(Collectors.toList());

누구든지 더 나은 / 빠른 솔루션을 가지고 있다면 알려주세요. 그러나이 솔루션은 불필요한 도우미 클래스 / 메소드를 추가하지 않고 메소드에 쉽게 포함시킬 수 있고 여전히 가독성을 유지하는 좋은 라이너입니다.


답변

list1.retainAll(list2) - is intersection

노동 조합이 될 것입니다 removeAll다음과addAll .

collection (ArrayList is collection) 문서에서 자세한 내용을 확인
하십시오. http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html


답변

합집합과 교집합은 목록이 아닌 세트에 대해서만 정의됩니다. 당신이 언급했듯이.

필터는 구아바 라이브러리를 확인하십시오 . 또한 구아바는 실제 교차로와 노조를 제공합니다

 static <E> Sets.SetView<E >union(Set<? extends E> set1, Set<? extends E> set2)
 static <E> Sets.SetView<E> intersection(Set<E> set1, Set<?> set2)


답변

당신은 아파치 커먼즈CollectionUtils 에서 사용할 수 있습니다 .


답변

표시된 솔루션이 효율적이지 않습니다. 시간 복잡도는 O (n ^ 2)입니다. 우리가 할 수있는 일은 두 목록을 정렬하고 아래와 같이 교차 알고리즘을 실행하는 것입니다.

private  static ArrayList<Integer> interesect(ArrayList<Integer> f, ArrayList<Integer> s) {
    ArrayList<Integer> res = new ArrayList<Integer>();

    int i = 0, j = 0;
    while (i != f.size() && j != s.size()) {

        if (f.get(i) < s.get(j)) {
            i ++;
        } else if (f.get(i) > s.get(j)) {
            j ++;
        } else {
            res.add(f.get(i));
            i ++;  j ++;
        }
    }


    return res;
}

이것은 O (n log n)에있는 O (n log n + n)의 복잡성을가집니다. 노조도 비슷한 방식으로 이루어집니다. if-elseif-else 문을 적절히 수정하십시오.

원하는 경우 반복자를 사용할 수도 있습니다 (C ++에서 더 효율적이라는 것을 알고 있습니다 .Java에서도 이것이 사실인지 모르겠습니다).