自定义Map的排序

按key排序

  • 自定义比较器comparator
  • 使用构造器TreeMap(comparator)
import java.util.*;

public class SortMapByKey {
	public static void main(String[] args) {
		originalOrdinal();	// order by key asc
		System.out.println();
		customizeOrdinal();	// 自定义Key的排列逻辑,灵活性更高。
	}

	static void originalOrdinal() {
		TreeMap<Integer, String> map = new TreeMap<>();	// 无参构造
		map.put(3, "three");
		map.put(1, "one");
		map.put(6, "six");
		map.put(7, "seven");
		for (Map.Entry entry : map.entrySet()) {
			System.out.println(entry);
		}
	}

	static void customizeOrdinal() {
		// 局部匿名类,有名对象descSeqRule。
		Comparator<Integer> descSeqRule = new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				int i1 = o1.intValue();
				int i2 = o2.intValue();
				if (i1 != i2) {
					return (i1 > i2) ? -1 : 1;
				} else {
					return 0;
				}
			}
		};
		// 向TreeMap的构造方法中传入一个自定义的比较器。
		// HashMap,LinkedHashMap,EnumMap类没有这样的构造器。所以只能用TreeMap。
		TreeMap<Integer, String> map = new TreeMap<>(descSeqRule);
		map.put(3, "three");
		map.put(1, "one");
		map.put(6, "six");
		map.put(7, "seven");
		for (Map.Entry entry : map.entrySet()) {
			System.out.println(entry);
		}
	}
}

输出结果:

1=one
3=three
6=six
7=seven

7=seven
6=six
3=three
1=one

显而易见:如果Key的类型为自定义类型(如Person,Node, Info),则可以通过自定义比较器,并将该比较器传入TreeMap的构造方法。这样生成的TreeMap类对象就会按照我们想要的排序逻辑对put进的Entry进行排列。

按value排序

  • 使用任意Map容器暂存所有要按照value的某种股则进行排序的Entry。
  • 使用一种List容器,接收之前map中的所有entry。
  • 自定义针对value的某种排列逻辑的比较器comparator。
  • Collections.sort(list, comparator)
  • 使用LinkedHashMap接收排序后的list中的元素。
import java.util.*;

public class SortMapByValue {
	public static void main(String[] args) {
		valueDescSeq();
	}
	
	static void valueDescSeq() {
		Map<Character, Integer> map = new TreeMap<Character, Integer>();
		map.put('t', 3);
		map.put('o', 1);
		map.put('s', 6);
		map.put('e', 8);

		Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();		// 数据源
		LinkedList<Map.Entry<Character, Integer>> list = new LinkedList<>();	// 目的地址
		for (Map.Entry<Character, Integer> entry : entrySet) {
			list.add(entry);
		}

		Comparator<Map.Entry<Character, Integer>> descValue = new Comparator<Map.Entry<Character, Integer>>() {
			@Override
			public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
				int i1 = o1.getValue().intValue();	// 也可以不获取intValue。两个Integer也可以用>等比较符号进行比较。
				int i2 = o2.getValue().intValue();	// 属于自动拆箱后的比较。而非运算符重载。
				if (i1 != i2) {
					return (i1 > i2) ? -1 : 1;
				} else {
					return 0;
				}
			}
		};
		Collections.sort(list, descValue);	// JDK API

		LinkedHashMap<Character, Integer> valueDescMap = new LinkedHashMap<Character, Integer>();
		for (Map.Entry<Character, Integer> entry: list) {
			valueDescMap.put(entry.getKey(), entry.getValue());
		}
		
		showMapByTraverseEntrySet(map);
		System.out.println();
		showMapByTraverseEntrySet(valueDescMap);

	}

	// 遍历map的两种方法,二选一。
	private static <K, V> void showMapByTraverseEntrySet(Map<K, V> map) {
		Set<Map.Entry<K, V>> entrySet = map.entrySet();
		for (Map.Entry<K, V> entry : entrySet) {
			System.out.println(entry);
		}
	}
	private static <K, V> void showMapByTraverseKeySet(Map<K, V> map) {
		Set<K> keySet = map.keySet();
		for (K key : keySet) {
			System.out.println(key + " = " + map.get(key));
		}
	}

}

输出结果:

e=8
o=1
s=6
t=3

e=8
s=6
t=3
o=1

依旧:map容器默认是按照key的XX(hashCode,还是说别的属性)进行排序。而此处key为Character类型,可以看出是按照ASCII码表顺序(数值增序)进行元素排列。
而如果我们的需求是按照value进行排序。则可以通过以上的方法进行操作。

猜你喜欢

转载自blog.csdn.net/wuyujin1997/article/details/82912869