[java] Java HashMap keySet () 반복 순서가 일치합니까?

지도의 keySet () 메서드에서 반환 된 Set이 특정 순서를 보장하지 않는다는 것을 이해합니다.

제 질문은 동일 하게 보장 됩니까? 여러 반복에 걸쳐 순서를 ? 예를 들면

Map<K,V> map = getMap();

for( K k : map.keySet() )
{
}

...

for( K k : map.keySet() )
{
}

위의 코드에서 맵이 수정 되지 않았다고 가정 하면 keySet에 대한 반복 순서가 동일합니다. Sun의 jdk15 IT 사용 않습니다 같은 순서로 반복 처리를,하지만이 동작에 의존하기 전에, 나는 모두의 JDK가 같은 행동을 할 것인지 알고 싶습니다.

편집하다

나는 그것에 의지 할 수없는 대답에서 봅니다. 너무 나쁘다. 주문을 보장하기 위해 새로운 컬렉션을 만들 필요가없는 상황에서 벗어나고 싶었습니다. 내 코드는 반복하고 논리를 수행 한 다음 동일한 순서로 다시 반복해야했습니다. 순서를 보장 할 keySet에서 새로운 ArrayList를 생성합니다.



답변

API 문서에 보증이 명시되어 있지 않다면 의존해서는 안됩니다. 동작은 동일한 공급 업체의 JDK에서도 JDK의 한 릴리스에서 다음 릴리스로 변경 될 수 있습니다.

당신은 쉽게 세트를 얻은 다음 직접 정렬 할 수 있습니다.


답변

LinkedHashMap을 사용할 수 있습니다.반복 순서가 변경되지 않는 HashMap을 원하는 경우 .

또한 컬렉션을 반복하는 경우 항상 사용해야합니다. HashMap의 entrySet 또는 keySet에 대한 반복은 LinkedHashMap보다 훨씬 느립니다.


답변

Map은 (클래스가 아니라) 인터페이스 일뿐입니다. 즉,이를 구현하는 기본 클래스가 다르게 동작 할 수 있으며 API의 keySet () 계약은 일관된 반복이 필요함을 나타내지 않습니다.

Map을 구현하는 특정 클래스 (HashMap, LinkedHashMap, TreeMap 등)를보고 있다면 소스를 확인하여 동작이 무엇인지 결정하기 위해 keySet () 함수를 구현하는 방법을 볼 수 있습니다. 알고리즘을 자세히 살펴보고 찾고있는 속성이 유지되는지 확인합니다 (즉, 맵에 반복 사이에 삽입 / 제거가없는 경우 일관된 반복 순서). 예를 들어 HashMap의 소스는 다음과 같습니다 (open JDK 6) : http://www.docjar.com/html/api/java/util/HashMap.java.html

JDK마다 크게 다를 수 있으므로 확실히 의존하지 않을 것입니다.

즉, 일관된 반복 순서가 정말로 필요한 경우 LinkedHashMap을 사용해 볼 수 있습니다.


답변

지도의 API는 보증하지 않습니다 어떤 경우에도 동일한 개체에 대한 방법의 여러 호출 사이, 어떠한 순서.

실제로는 여러 후속 호출에 대해 반복 순서가 변경되면 매우 놀라 울 것입니다 (맵 자체가 그 사이에 변경되지 않았다고 가정).하지만 API에 따라 이에 의존해서는 안됩니다.

편집-일관된 반복 순서에 의존하려면 정확히 이러한 보장을 제공 하는 SortedMap 을 원합니다 .


답변

재미로 매번 무작위 순서를 보장하는 데 사용할 수있는 코드를 작성하기로 결정했습니다. 이것은 주문에 의존하지만 그렇게해서는 안되는 경우를 포착 할 수 있도록 유용합니다. 다른 사람들이 말한 것보다 순서에 의존하려면 SortedMap을 사용해야합니다. Map을 사용하고 순서에 의존하는 경우 다음 RandomIterator를 사용하면이를 파악할 수 있습니다. 더 많은 메모리를 사용하기 때문에 테스트 코드에서만 사용합니다.

또한 Map (또는 Set)을 래핑하여 RandomeIterator를 반환하도록 할 수 있습니다. 그러면 for-each 루프를 사용할 수 있습니다.

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class Main
{
    private Main()
    {
    }

    public static void main(final String[] args)
    {
        final Map<String, String> items;

        items = new HashMap<String, String>();
        items.put("A", "1");
        items.put("B", "2");
        items.put("C", "3");
        items.put("D", "4");
        items.put("E", "5");
        items.put("F", "6");
        items.put("G", "7");

        display(items.keySet().iterator());
        System.out.println("---");

        display(items.keySet().iterator());
        System.out.println("---");

        display(new RandomIterator<String>(items.keySet().iterator()));
        System.out.println("---");

        display(new RandomIterator<String>(items.keySet().iterator()));
        System.out.println("---");
    }

    private static <T> void display(final Iterator<T> iterator)
    {
        while(iterator.hasNext())
        {
            final T item;

            item = iterator.next();
            System.out.println(item);
        }
    }
}

class RandomIterator<T>
    implements Iterator<T>
{
    private final Iterator<T> iterator;

    public RandomIterator(final Iterator<T> i)
    {
        final List<T> items;

        items = new ArrayList<T>();

        while(i.hasNext())
        {
            final T item;

            item = i.next();
            items.add(item);
        }

        Collections.shuffle(items);
        iterator = items.iterator();
    }

    public boolean hasNext()
    {
        return (iterator.hasNext());
    }

    public T next()
    {
        return (iterator.next());
    }

    public void remove()
    {
        iterator.remove();
    }
}


답변

LinkedHashMap에 동의합니다. 키로 HashMap을 정렬하려고 할 때 문제에 직면했을 때 내 발견과 경험을 넣었습니다.

HashMap을 만드는 코드 :

HashMap<Integer, String> map;

@Before
public void initData() {
    map = new HashMap<>();

    map.put(55, "John");
    map.put(22, "Apple");
    map.put(66, "Earl");
    map.put(77, "Pearl");
    map.put(12, "George");
    map.put(6, "Rocky");

}

지도 항목을 인쇄하는 함수 showMap이 있습니다.

public void showMap (Map<Integer, String> map1) {
    for (Map.Entry<Integer,  String> entry: map1.entrySet()) {
        System.out.println("[Key: "+entry.getKey()+ " , "+"Value: "+entry.getValue() +"] ");

    }

}

이제 정렬하기 전에지도를 인쇄하면 다음과 같은 순서로 인쇄됩니다.

Map before sorting :
[Key: 66 , Value: Earl]
[Key: 22 , Value: Apple]
[Key: 6 , Value: Rocky]
[Key: 55 , Value: John]
[Key: 12 , Value: George]
[Key: 77 , Value: Pearl]

기본적으로 맵 키를 넣은 순서와 다릅니다.

이제 맵 키로 정렬 할 때 :

    List<Map.Entry<Integer, String>> entries = new ArrayList<>(map.entrySet());

    Collections.sort(entries, new Comparator<Entry<Integer, String>>() {

        @Override
        public int compare(Entry<Integer, String> o1, Entry<Integer, String> o2) {

            return o1.getKey().compareTo(o2.getKey());
        }
    });

    HashMap<Integer, String> sortedMap = new LinkedHashMap<>();

    for (Map.Entry<Integer, String> entry : entries) {
        System.out.println("Putting key:"+entry.getKey());
        sortedMap.put(entry.getKey(), entry.getValue());
    }

    System.out.println("Map after sorting:");

    showMap(sortedMap);

출력은 다음과 같습니다.

Sorting by keys :
Putting key:6
Putting key:12
Putting key:22
Putting key:55
Putting key:66
Putting key:77
Map after sorting:
[Key: 66 , Value: Earl]
[Key: 6 , Value: Rocky]
[Key: 22 , Value: Apple]
[Key: 55 , Value: John]
[Key: 12 , Value: George]
[Key: 77 , Value: Pearl]

키 순서의 차이를 확인할 수 있습니다. 정렬 된 키 순서는 괜찮지 만 복사 된 맵의 키 순서는 이전 맵의 순서와 동일합니다. 이것이 유효한지 모르겠지만 동일한 키를 가진 두 개의 해시 맵의 경우 키 순서가 동일합니다. 이것은 키의 순서가 보장되지는 않지만이 JVM 버전의 HashMap이 구현 된 경우 키 삽입 알고리즘의 고유 한 특성으로 인해 동일한 키를 가진 두 개의 맵에 대해 동일 할 수 있음을 의미합니다.

이제 LinkedHashMap을 사용하여 정렬 된 항목을 HashMap에 복사 할 때 원하는 결과를 얻습니다 (자연 스럽지만 포인트는 아닙니다. 포인트는 HashMap의 키 순서에 관한 것입니다).

    HashMap<Integer, String> sortedMap = new LinkedHashMap<>();

    for (Map.Entry<Integer, String> entry : entries) {
        System.out.println("Putting key:"+entry.getKey());
        sortedMap.put(entry.getKey(), entry.getValue());
    }

    System.out.println("Map after sorting:");

    showMap(sortedMap);

산출:

Sorting by keys :
Putting key:6
Putting key:12
Putting key:22
Putting key:55
Putting key:66
Putting key:77
Map after sorting:
[Key: 6 , Value: Rocky]
[Key: 12 , Value: George]
[Key: 22 , Value: Apple]
[Key: 55 , Value: John]
[Key: 66 , Value: Earl]
[Key: 77 , Value: Pearl]


답변

Hashmap은 맵의 순서가 시간이 지남에 따라 일정하게 유지된다는 것을 보장하지 않습니다.