컬렉션을 목록으로 변환하는 방법?


294

Apache Collections 라이브러리 TreeBidiMap에서 사용 하고 있습니다. 이 값을 정렬하고 싶습니다 .doubles

내 방법은 다음을 Collection사용하여 값 을 검색하는 것 입니다.

Collection coll = themap.values();

자연스럽게 잘 작동합니다.

주요 질문 : 이제 어떻게 정렬 / 변환 (정확한지 확실하지 않음) collList정렬 할 수 있는지 알고 싶습니다 .

그런 다음 정렬 된 List객체 를 반복하려고 합니다. 순서가 있어야하며 반복자가 목록 위에있는 위치를 사용하여 TreeBidiMap( themap) 에서 적절한 키를 가져옵니다 .themap.getKey(iterator.next())doubles


4
일종의 SortedMap을 직접 사용하여이 단계를 피할 수 있으므로 항목이 사용되는 키 순서대로 자연스럽게 표시됩니다. Java의 자체 TreeMap은 SortedMap을 구현합니다.
Axel Knauf

TreeBidiMap입니다 OrderedMap, 순서는 괜찮을 것입니다. 질문에 필요한 정렬은 키가 아닌 값을 기준으로합니다.
Vlasec

답변:


470
List list = new ArrayList(coll);
Collections.sort(list);

Erel Segal Halevi가 아래에 언급했듯이 coll이 이미 목록 인 경우 1 단계를 건너 뛸 수 있습니다. 그러나 그것은 TreeBidiMap의 내부에 달려 있습니다.

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);

4
두 가지 접근 방식에는 다른 부작용이 있습니다. 컬렉션을 목록으로 캐스팅 한 다음 정렬하면 원래 컬렉션도 정렬됩니다. 사본을 만들지 않습니다.
바니

이 방법을 반복적으로 사용하면 성능이 크게 저하됩니다. 즉석에서 작동하는 솔루션에 대한 대답은 사용자 정의 컬렉션과 관련이 있습니다.
Vlasec

map.values ​​()가 "inner class"컬렉션을 반환하는 경우에는 해결되지 않습니다. 컴파일러는 Collections.sort (List <T>)가 Collections.sort (List <InnerClass>)를 허용하지 않는다고보고합니다. 해결 방법은 다음과 같습니다. List <InnerClass> list = map.values ​​(). stream (). collect (Collectors.toList ())
Pereira


33

coll이 이미 목록 인 경우 Paul Tomblin의 답변이 낭비 될 수 있습니다. 새로운 목록을 만들고 모든 요소를 ​​복사하기 때문입니다. coll에 많은 elemeent가 포함되어 있으면 시간이 오래 걸릴 수 있습니다.

내 제안은 :

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);

21

나는 당신이 그것을 다음과 같이 쓸 수 있다고 생각합니다.

coll.stream().collect(Collectors.toList())

더 나은 방법은 캐스팅 주변 얻을
Stackee007

큰! 이것은 내 사건을 해결했습니다. 내 map.values ​​()는 "내부 클래스"컬렉션을 반환합니다. 컴파일러는 Collections.sort (List <T>)가 Collections.sort (List <InnerClass>)를 허용하지 않는다고보고했습니다.
Pereira

안드로이드에서 유스 케이스로 작동하지 않았습니다. 최소 api 24 필요
ansh sachdeva

8
Collections.sort( new ArrayList( coll ) );

ArrayList에 액세스하기위한 참조가 없습니까?
Zach Scrivena

@ 자흐 : 음 좋은 지적. CW로 표시해야 할 이유가 있다는 것을 알았습니다. BTW 바울의 대답은 바로 그 것입니다. 왜 내 UV 만 가지고 있는지 모르겠어요
OscarRyz

4

@ 쿠니 가미 : 구아바의 newArrayList방법 에 대해 착각 한 것 같습니다 . Iterable이 List 유형인지 확인하지 않고 주어진 목록을 그대로 리턴합니다. 그것은 항상 새 목록을 생성합니다 :

@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
  checkNotNull(elements); // for GWT
  // Let ArrayList's sizing logic work, if possible
  return (elements instanceof Collection)
      ? new ArrayList<E>(Collections2.cast(elements))
      : newArrayList(elements.iterator());
}

이것은 어떻게 더 많이 투표되지 않습니까? Kunigami의 답변은 (기본 구현에 대해 가정하는 한) 부정확합니다.
GreenieMeanie

0

요청한 작업은 비용이 많이 드는 작업이므로 자주 수행하지 않아도됩니다 (예 :주기).

그렇지 않으면 사용자 지정 컬렉션을 만들 수 있습니다. 나는 당신 TreeBidiMap과 그 TreeMultiset아래에있는 것을 생각해 냈습니다 . 필요한 것만 구현하고 데이터 무결성을 관리하십시오.

class MyCustomCollection implements Map<K, V> {
    TreeBidiMap<K, V> map;
    TreeMultiset<V> multiset;
    public V put(K key, V value) {
        removeValue(map.put(key, value));
        multiset.add(value);
    }
    public boolean remove(K key) {
        removeValue(map.remove(key));
    }
    /** removes value that was removed/replaced in map */
    private removeValue(V value) {
        if (value != null) {
            multiset.remove(value);
        }
    }
    public Set keySet() {
        return map.keySet();
    }
    public Multiset values() {
        return multiset;
    }
    // many more methods to be implemented, e.g. count, isEmpty etc.
}

이 방법으로, 당신은 정렬 된 Multiset 반환values() . 그러나리스트가되어야한다면 (예를 들어, 배열과 같은 get(index)방법 이 필요하다면 ) 좀 더 복잡한 것을 발명해야합니다.


keySet()그리고 values()보기는 원본 Map에 대한 것이므로 수정 될 때 백업도 수정 Map해야합니다. 솔루션이이를 지원하지 않습니다
Lino

-4

다음은 단일 라이너로 최적이 아닌 솔루션입니다.

Collections.list(Collections.enumeration(coll));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.