Java에서 키별로 맵 값을 정렬하는 방법은 무엇입니까?


361

키와 값 모두에 대한 문자열이있는 맵이 있습니다.

데이터는 다음과 같습니다.

"question1", "1"
"question9", "1"
"question2", "4"
"question5", "2"

키를 기준으로 맵을 정렬하고 싶습니다. 결국에는 question1, question2, question3.... 등이 있습니다.


결국, 나는이 맵에서 두 개의 문자열을 얻으려고합니다.

  • 첫 번째 문자열 : 질문 (1.10 순서)
  • 두 번째 문자열 : 답변 (질문과 같은 순서로)

지금 나는 다음을 가지고 있습니다.

Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry pairs = (Map.Entry) it.next();
    questionAnswers += pairs.getKey() + ",";
}

이것은 나에게 문자열로 질문을 받지만 순서가 맞지 않습니다.

답변:


612

짧은 답변

를 사용하십시오 TreeMap. 이것이 바로 그 목적입니다.

이지도가 전달되어 유형을 결정할 수없는 경우 다음을 수행 할 수 있습니다.

SortedSet<String> keys = new TreeSet<>(map.keySet());
for (String key : keys) { 
   String value = map.get(key);
   // do something
}

이것은 자연스럽게 키 순서대로 맵을 반복합니다.


더 긴 답변

기술적으로 구현하는 모든 것을 사용할 수 SortedMap있지만 드문 경우를 제외하고 TreeMapMap구현 을 사용하는 것이 일반적으로 그렇듯이이 정도에 해당합니다 HashMap.

Comparable를 구현하지 않거나 다음 자연의 질서를 사용하지 않으려는 키가 복잡한 유형의 경우를 들어 TreeMap그리고 TreeSet당신이 전달하자 추가 생성자를 가지고 Comparator:

// placed inline for the demonstration, but doesn't have to be a lambda expression
Comparator<Foo> comparator = (Foo o1, Foo o2) -> {
        ...
    }

SortedSet<Foo> keys = new TreeSet<>(comparator);
keys.addAll(map.keySet());

를 사용할 때 기억 TreeMapTreeSet는 다른 성능 특성있을 것이라는 점을 HashMap또는 HashSet. 요소를 찾거나 삽입하는 대략적인 연산은 O (1) 에서 O (Log (N))로 이동 합니다.

A의 HashMap1 만 1000 개 항목에서 이동하는 것은 정말 요소를 조회하는 시간에 영향을 미치지 않지만, 대한 TreeMap조회 시간은 약 3 배 더 느리게 (로그인 가정 할 것이다 2 ). 1000에서 100,000으로 이동하면 모든 요소 조회에 대해 약 6 배 느려집니다.


트리 맵을 사용하고 길이를 기준으로 문자열 키를 정렬하려고합니다. 일치하지 않는 검색 결과가 나타납니다. TreeMap은 0의 compareTo 결과를 "같음"으로 간주하기 때문에? 이 경우 사용법을 잘 모릅니다.
Marc

1
compareTo () 결과 0은 '같음'입니다. 문자열 길이를 기준으로 정렬하는 비교자를 작성하는 경우 어떤 문자열이 더 긴지에 따라 양수 또는 음수 값을 반환하고 두 문자열의 길이가 같은 경우에만 0을 반환해야합니다. a와 b가 문자열이라면`return a.length ()-b.length () '와 같이 할 수 있습니다 (또는 다른 방향으로 정렬하려면 값을 되돌립니다).
Jherico

안녕하세요 여러분,지도에 1,2,3,4 인 키로 주문하려면 삽입 순서는 무엇입니까? ... 왜 우리는 LinkedHashSet을 사용하지 않습니까? 우리는 질문을 하나씩 하나씩 넣었고 삽입 순서에 따라 순서를 정했습니다. 이것으로 나를 도울 수 있습니까?
Karoly

@Karoly LinkedHashSet은 요소를 삽입 한 순서대로 검색합니다. OP가 원하는 것은 삽입 순서에 관계없이 미리 정해진 정렬 순서로 요소를 검색하는 것입니다.
데이비드 베리

@ cricket_007 코드는 아직 정렬되지 않은 맵에 대해 키를 반복하는 방법을 구체적으로 보여줍니다.
Jherico

137

TreeMap이 좋지 않다고 가정하고 제네릭을 사용할 수 없다고 가정합니다.

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.

3
감사! 키가 복잡한 유형이므로 이와 같은 작업을 수행해야했습니다.
로스 햄브릭

3
키 목록 만 정렬하지만 키를 기준으로 맵 자체는 정렬하지 않습니다. 또한 키를 기준으로지도를 정렬하는 방법을 찾고 있으며 방법을 찾을 수 있습니다. 나는 TreeMap와 함께 시도해야 할 것 같아요 :)
Crenguta S

55

를 사용하여 TreeMap지도를 정렬 할 수 있습니다.

Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}

1
Map <String, List <String >> treeMap = 새 TreeMap <String, List <String >> (printHashMap); for (String str : treeMap.keySet ()) {System.out.println (str + ""+ treeMap.get (str)); }
vikramvi

37

TreeMap을 사용하십시오 !


31
+1-Jherico, Jon을 이길만큼 민첩하지는 않지만 여전히 훌륭합니다. 8)
duffymo

나는 자바를 모르는 :-(이 100 % 작동하는이 끔찍한 솔루션들보다 훨씬 더 간단 내가 함께했다.
peterchaula

36

이미 맵이 있고 키로 정렬하려면 다음을 사용하십시오.

Map<String, String> treeMap = new TreeMap<String, String>(yourMap);

완전한 작업 예 :

import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;

class SortOnKey {

public static void main(String[] args) {
   HashMap<String,String> hm = new HashMap<String,String>();
   hm.put("3","three");
   hm.put("1","one");
   hm.put("4","four");
   hm.put("2","two");
   printMap(hm);
   Map<String, String> treeMap = new TreeMap<String, String>(hm);
   printMap(treeMap);
}//main

public static void printMap(Map<String,String> map) {
    Set s = map.entrySet();
    Iterator it = s.iterator();
    while ( it.hasNext() ) {
       Map.Entry entry = (Map.Entry) it.next();
       String key = (String) entry.getKey();
       String value = (String) entry.getValue();
       System.out.println(key + " => " + value);
    }//while
    System.out.println("========================");
}//printMap

}//class

36

그냥 TreeMap을 사용하십시오

new TreeMap<String, String>(unsortMap);

TreeMap은 '키'의 자연 순서에 따라 정렬됩니다.


19

당신이 사용할 수 없습니다 제공 TreeMap자바 (8) 우리는 사용 할 수 toMap () 메서드에서 Collectors어떤 매개 변수 다음 걸립니다를 :

  • keymapper : 키를 생성하는 매핑 기능
  • valuemapper : 값을 생성하는 매핑 함수
  • mergeFunction : 동일한 키와 연관된 값 사이의 충돌을 해결하는 데 사용되는 병합 함수
  • mapSupplier : 결과가 삽입 될 비어있는 새 맵을 리턴하는 함수입니다.

자바 8 예제

Map<String,String> sample = new HashMap<>();  // push some values to map  
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                    .sorted(Map.Entry.<String,String>comparingByKey().reversed())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
Map<String, String> newMapSortedByValue = sample.entrySet().stream()
                        .sorted(Map.Entry.<String,String>comparingByValue().reversed())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

커스텀 비교기를 사용하고 다음과 같이 키를 기준으로 정렬하도록 예제를 수정할 수 있습니다.

Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                .sorted((e1,e2) -> e1.getKey().compareTo(e2.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

Api 24 이상이 설치된 Android에서만 작동합니다.
Tina

9

사용 자바 8 :

Map<String, Integer> sortedMap = unsortMap.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

5

이 코드는 키-값 맵을 오름차순과 내림차순으로 정렬 할 수 있습니다.

<K, V extends Comparable<V>> Map<K, V> sortByValues
     (final Map<K, V> map, int ascending)
{
     Comparator<K> valueComparator =  new Comparator<K>() {         
        private int ascending;
        public int compare(K k1, K k2) {
            int compare = map.get(k2).compareTo(map.get(k1));
            if (compare == 0) return 1;
            else return ascending*compare;
        }
        public Comparator<K> setParam(int ascending)
        {
            this.ascending = ascending;
            return this;
        }
    }.setParam(ascending);

    Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
    sortedByValues.putAll(map);
    return sortedByValues;
}

예로서:

Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1);  // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1);  // Descending order

5

자바 8에서

Map<K, V>키 를 기준으로 정렬하려면 키를 List<K>:

List<K> result = map.keySet().stream().sorted().collect(Collectors.toList());

Map<K, V>키 를 기준으로 정렬하려면 다음과 같이 입력하십시오 List<Map.Entry<K, V>>.

List<Map.Entry<K, V>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey())
       .collect(Collectors.toList());

마지막 으로, 로케일 구분 방식으로 문자열 을 정렬하려면 Collator (comparator) 클래스를 사용하십시오.

Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.PRIMARY); // case insensitive collator

List<Map.Entry<String, String>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey(collator))
       .collect(Collectors.toList());

1
List<String> list = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String str : map.keySet()) {
 list.add(str);
}
Collections.sort(list);
for (String str : list) {
 System.out.println(str);
}

1

Java 8에서는 .stream (). sorted ()를 사용할 수도 있습니다.

myMap.keySet().stream().sorted().forEach(key -> {
        String value = myMap.get(key);

        System.out.println("key: " + key);
        System.out.println("value: " + value);
    }
);

0

Arrays.sort 메서드를 사용하여 키를 정렬 할 수도 있습니다.

Map<String, String> map = new HashMap<String, String>();
Object[] objArr = new Object[map.size()];
for (int i = 0; i < map.size(); i++) {
objArr[i] = map.get(i);
}
Arrays.sort(objArr);
for (Object str : objArr) {
System.out.println(str);
}

이것은 키가 아닌 값으로 정렬됩니다.
raaj

0

당신이 사용하고 싶지 않은 경우에 대비하여 TreeMap

public static Map<Integer, Integer> sortByKey(Map<Integer, Integer> map) {
    List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());
    list.sort(Comparator.comparingInt(Map.Entry::getKey));
    Map<Integer, Integer> sortedMap = new HashMap<>();
    list.forEach(sortedMap.put(e.getKey(), e.getValue()));
    return sortedMap;
}

또한을 values변경 Map.Entry::getKey하기 만하면 지도를 정렬하려는 경우Map.Entry::getValue


이것은 내 검토 로그에 나타났습니다. 누군가 변수 이름으로 오류를 수정하려고했지만 실패했습니다. 그래서 나는 그것들을 올바르게 고쳤 지 만,이 대답은 근본적으로 잘못되었습니다. HashMap에 값을 추가하는 순서는 관련이 없습니다. 지도에 주문이 없습니다. stackoverflow.com/questions/10710193/…
aepryus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.