값별 트리 맵 정렬
기본 자연순서가 아닌 값으로 TreeMap을 정렬할 수 있는 비교기를 작성하려고 합니다.
다음과 같이 시도했지만 무엇이 잘못되었는지 찾을 수 없습니다.
import java.util.*;
class treeMap {
public static void main(String[] args) {
System.out.println("the main");
byValue cmp = new byValue();
Map<String, Integer> map = new TreeMap<String, Integer>(cmp);
map.put("de",10);
map.put("ab", 20);
map.put("a",5);
for (Map.Entry<String,Integer> pair: map.entrySet()) {
System.out.println(pair.getKey()+":"+pair.getValue());
}
}
}
class byValue implements Comparator<Map.Entry<String,Integer>> {
public int compare(Map.Entry<String,Integer> e1, Map.Entry<String,Integer> e2) {
if (e1.getValue() < e2.getValue()){
return 1;
} else if (e1.getValue() == e2.getValue()) {
return 0;
} else {
return -1;
}
}
}
가 받을 수 건, 가 a a a a a a a a a a a a a a a a a a a a a a a a a?Map.Entry
조군군? 츠요시
안 TreeMap
이는 사양에 어긋나기 때문에 값을 기준으로 정렬됩니다.
A
Map
또한 키 전체 주문을 제공합니다.
그러나 외부 컬렉션을 사용하면 키, 값 또는 두 가지 조합(!)을 기준으로 언제든지 원하는 대로 정렬할 수 있습니다.
이 있습니다.SortedSet
Map.Entry
( 「」가 됩니다)Map
은 " " " 입니다.Comparable
:
static <K,V extends Comparable<? super V>>
SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1;
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
이제 다음을 수행할 수 있습니다.
Map<String,Integer> map = new TreeMap<String,Integer>();
map.put("A", 3);
map.put("B", 2);
map.put("C", 1);
System.out.println(map);
// prints "{A=3, B=2, C=1}"
System.out.println(entriesSortedByValues(map));
// prints "[C=1, B=2, A=3]"
만약 이 어느쪽인가를 일이 수 것에 하세요.SortedSet
자체 " " " 입니다.Map.Entry
는 더 의 '입니다.entrySet()
empty.month.mpti.
일반적으로 맵의 엔트리를 값별로 정렬할 필요는 없습니다.
★★★★★★★★★★★==
★★★★★★에Integer
가 비교하고 있습니다.Integer
를 사용합니다.==
이것은 거의 항상 틀립니다.==
Integer
피연산자는 참조 등식이지 값 등식이 아닙니다.
System.out.println(new Integer(0) == new Integer(0)); // prints "false"!!!
관련 질문
- Java에서 두 정수 비교 시 자동 언박스가 발생합니까? (NO!!!)
- Java에서는 보증됩니까? (YES!!)
다원성 유산균의 답은 거의 완벽합니다.하지만 중요한 버그가 하나 있어요.값이 같은 맵엔트리는 처리되지 않습니다.
이 코드:
Map<String, Integer> nonSortedMap = new HashMap<String, Integer>();
nonSortedMap.put("ape", 1);
nonSortedMap.put("pig", 3);
nonSortedMap.put("cow", 1);
nonSortedMap.put("frog", 2);
for (Entry<String, Integer> entry : entriesSortedByValues(nonSortedMap)) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
출력:
ape:1
frog:2
pig:3
우리 소가 원숭이:O와 값 "1"을 공유하면서 어떻게 사라졌는지 주목하세요!
이 코드의 수정에 의해, 다음의 문제가 해결됩니다.
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1; // Special fix to preserve items with equal values
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
Java 8의 경우:
LinkedHashMap<Integer, String> sortedMap = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue(/* Optional: Comparator.reverseOrder() */))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
A TreeMap
항상 키에 따라 정렬됩니다. 다른 건 불가능하죠.aComparator
키를 정렬하는 방법만 제어할 수 있습니다.
값을 해야 .List
그걸 분류해 주세요.
안 돼요, 하다, 하다, 하다, 하다, 이렇게 안 요.Comparator
비교하기 위한 맵의 키가 항상 취득되기 때문입니다. TreeMap
는 키로만 정렬할 수 있습니다.
올로프의 대답은 좋지만, 완벽해지기 위해서는 한 가지가 더 필요하다.아래의 코멘트에서 dacwe(올바르게)는 자신의 구현이 세트에 대한 비교/균등 계약을 위반한다고 지적합니다.세트 내에 명확하게 존재하는 엔트리에서 콜을 포함 또는 삭제하려고 하면 동일한 값을 가진 엔트리를 세트에 배치할 수 있는 코드 때문에 세트는 해당 엔트리를 인식하지 않습니다.따라서 이 문제를 해결하려면 키 간의 동일성을 테스트해야 합니다.
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
if (e1.getKey().equals(e2.getKey())) {
return res; // Code will now handle equality properly
} else {
return res != 0 ? res : 1; // While still adding all entries
}
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
"소트된 세트가 Set 인터페이스를 올바르게 구현하려면 (명시적인 비교기 제공 여부에 관계없이) 정렬된 세트에 의해 유지되는 순서는 동등과 일치해야 합니다.Set 인터페이스는 등가 연산의 관점에서 정의되지만 정렬된 세트는 compareTo(또는 비교) 메서드를 사용하여 모든 요소 비교를 수행하므로 이 메서드에 의해 동등하다고 간주되는2개의 요소는 정렬된 세트의 관점에서 동등합니다.
원래 동등한 값을 가진 엔트리를 강제로 추가하기 위해 동등성을 간과했으므로, 이제는 실제로 원하는 엔트리를 반환하기 위해 키의 동일성을 테스트해야 합니다.이것은 좀 지저분하고 세트장 사용방법은 확실히 아니지만 작동한다.
이 투고에서는 특히 TreeMap을 값별로 정렬할 것을 요구하고 있는 것을 알고 있습니다만, 실장에는 별로 관심이 없지만, 요소가 추가되었을 때 컬렉션을 정렬해 두는 솔루션을 원하는 분은 이 TreeSet 기반 솔루션에 대한 피드백을 주시면 감사하겠습니다.하나는 키로 요소를 쉽게 검색할 수 없지만, 내가 가지고 있는 사용 사례(최저값의 n개의 키를 찾는 것)에서는 이것이 요건이 아니었다.
TreeSet<Map.Entry<Integer, Double>> set = new TreeSet<>(new Comparator<Map.Entry<Integer, Double>>()
{
@Override
public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2)
{
int valueComparison = o1.getValue().compareTo(o2.getValue());
return valueComparison == 0 ? o1.getKey().compareTo(o2.getKey()) : valueComparison;
}
});
int key = 5;
double value = 1.0;
set.add(new AbstractMap.SimpleEntry<>(key, value));
많은 사람들이 List를 사용하라는 조언을 듣고 나도 List를 사용하는 것을 선호한다.
Map의 엔트리를 값에 따라 정렬하기 위해 필요한 두 가지 방법이 있습니다.
static final Comparator<Entry<?, Double>> DOUBLE_VALUE_COMPARATOR =
new Comparator<Entry<?, Double>>() {
@Override
public int compare(Entry<?, Double> o1, Entry<?, Double> o2) {
return o1.getValue().compareTo(o2.getValue());
}
};
static final List<Entry<?, Double>> sortHashMapByDoubleValue(HashMap temp)
{
Set<Entry<?, Double>> entryOfMap = temp.entrySet();
List<Entry<?, Double>> entries = new ArrayList<Entry<?, Double>>(entryOfMap);
Collections.sort(entries, DOUBLE_VALUE_COMPARATOR);
return entries;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
TreeMap<String, Integer> initTree = new TreeMap();
initTree.put("D", 0);
initTree.put("C", -3);
initTree.put("A", 43);
initTree.put("B", 32);
System.out.println("Sorted by keys:");
System.out.println(initTree);
List list = new ArrayList(initTree.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
System.out.println("Sorted by values:");
System.out.println(list);
}
}
//convert HashMap into List
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
Collections.sort(list, (o1, o2) -> o1.getValue().compareTo(o2.getValue()));
해시 맵을 사용하는 경우 Comparator에서 먼저 값을 확인하는 조건을 추가하고 값이 동일한 경우 키를 정렬합니다.
HashMap<String , Integer> polpularity = new HashMap<>();
List<String> collect = popularity.entrySet().stream().sorted((t2, t1) -> {
if (t2.getValue() > t1.getValue()) {
return -1;
} else if (t2.getValue() < t1.getValue()) {
return +1;
} else {
return t2.getKey().compareTo(t1.getKey());
}
}).map(entry -> entry.getKey()).collect(Collectors.toList());
후자의 상태를 관리하고 싶지 않은 경우 트리맵을 사용하여 자동으로 정렬할 수 있습니다.이 작업은 우아한 코드 한 줄로 수행할 수 있습니다.
TreeMap<String, Integer> popularity = new TreeMap<>();
List<String> collect = popularity.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).map(entry -> entry.getKey()).collect(Collectors.toList());
언급URL : https://stackoverflow.com/questions/2864840/treemap-sort-by-value
'sourcecode' 카테고리의 다른 글
권장되는 VueJS 애플리케이션 API 및 Vuex 설계 패턴이 있습니까? (0) | 2022.07.28 |
---|---|
C++ 프로그램에 대한 C 라이브러리 사용 (0) | 2022.07.27 |
항아리 유물의 메이븐 최종 이름 제어 (0) | 2022.07.27 |
Vue.js가 컴포넌트 내부에 부울 변경을 저장합니다. (0) | 2022.07.27 |
온도 변수 때문에 프로그램이 느려집니까? (0) | 2022.07.27 |