1、Map集合
1.1Map集合介绍
现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等, 这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map
接 口。
1.2Map继承关系
(1):AbstractMap
是一个抽象类, 继承Map,实现了Map的大部分API,它的作用Map的实现类继承它,可以减少重复编码!
(2):SortedMap
是一个接口 继承Map,自己也封装一下方法,SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。SortedMap的排序方式有两种:自然排序 或者 用户指定比较器。
(3):ConcurrentMap
是一个接口,并且继承Map接口,在java.util.concurrent
包下!
(4):HashMap
继承于AbstractMap,HashMap的内容是“键值对,但不保证次序”!
(5): TreeMap
继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是键值对,有序的键值对!
(6):ConcurrentHashMap
继承AbstractMap实现ConcurrentMap,是一个并发的哈希表!此类与 Hashtable 相似,但与 HashMap 不同,它不允许将 null 用作键或值。线程安全,但是实现方法和Hashtable完全不同(并发情况可以使用) 。
(7):Dictionary
是一个抽象类(数据字典),HashTable继承Dictionary并实现Map接口,也是键值对,但不保证次序!Hashtable
是线程安全的,而且它支持通过Enumeration去遍历。(现在使用很少,并发操作效率太低)
1.3Map集合与Collection集合存储形式的不同
-
Collection
中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。 -
Map
中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。 - Collection 中的集合称为单列集合, Map 中的集合称为双列集合。
- 需要注意的是, Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
1.4Map常用方法
void clear()
从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
boolean equals(Object o)
比较指定的对象与此映射是否相等。
V get(Object key)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
int hashCode()
返回此映射的哈希码值。
boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true。
V put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。
V remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size()
返回此映射中的键-值映射关系数。
Set<K> keySet()
用于返回Key集的Set合
Set<Map.Entry<K,V>> entrySet()
用于返回<Key——Value> 集的Set集合
Collection<V> values()
用于返回value集的Collection集合。
Map接口常用方法演示:
import java.util.HashMap;
public class test {
public static void main(String[] args) {
//创建 map对象
HashMap<String, String> map = new HashMap<String, String>();
//添加元素到集合
map.put("黄晓明", "杨颖");
map.put("文章", "马伊琍");
map.put("邓超", "孙俪");
System.out.println(map);
//String remove(String key)
//把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的 值
System.out.println(map.remove("文章"));
System.out.println(map);
// 根据指定的键,在Map集合中获取对应的值
System.out.println(map.get("黄晓明"));
System.out.println(map.get("邓超"));
}
}
{邓超=孙俪, 文章=马伊琍, 黄晓明=杨颖}
马伊琍
{邓超=孙俪, 黄晓明=杨颖}
杨颖
孙俪
(注意:在使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到 集合中; 若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的 值,替换成指定的新值。)
1.5Map集合遍历键找值方式
键找值方式:即通过元素中的键,获取键所对应的值
操作步骤:
- 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示: keyset()
- 遍历键的Set集合,得到每一个键。
- 根据键,获取键所对应的值。方法提示: get(K key)
(Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了)
import java.util.HashMap;
import java.util.Set;
public class test {
public static void main(String[] args)
{
//创建Map集合对象
HashMap<String, String> map = new HashMap<String,String>();
//添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
//获取所有的键 获取键集
Set<String> keys = map.keySet();
// 遍历键集 得到 每一个键
for (String key : keys)
{
//key 就是键
//获取对应值
String value = map.get(key);
System.out.println(key+"的CP是:"+value);
}
}
}
郭德纲的CP是:于谦
薛之谦的CP是:大张伟
胡歌的CP是:霍建华
遍历图解:
1.6Entry键值对对象
我们已经知道, Map 中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在 Map 中是一一对应关 系
,这一对对象又称做 Map 中的一个 Entry(项)
。 Entry 将键值对的对应关系封装成了对象。即键值对对象,这 样我们在遍历 Map 集合时,就可以从每一个键值对( Entry )对象中获取对应的键与对应的值。 既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法:
-
public K getKey()
:获取Entry对象中的键。 -
public V getValue()
:获取Entry对象中的值。
在Map集合中也提供了获取所有Entry对象的方法:
-
public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。
1.7Map集合遍历键值对方式
遍历键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
操作步骤:
- 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示: entrySet() 。
- 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
- 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示: getkey() getValue()
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class test {
public static void main(String[] args)
{
// 创建Map集合对象
HashMap<String, String> map = new HashMap<String,String>();
// 添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
// 获取 所有的 entry对象 entrySet
Set<Entry<String,String>> entrySet = map.entrySet();
// 遍历得到每一个entry对象
for (Entry<String, String> entry : entrySet)
{
// 解析
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"的CP是:"+value);
}
}
}
郭德纲的CP是:于谦
薛之谦的CP是:大张伟
胡歌的CP是:霍建华
遍历图解:
1.8Map集合练习
题目:计算一个字符串中每个字符出现次数。
分析:
- 获取一个字符串对象
- 创建一个Map集合,键代表字符,值代表次数。
- 遍历字符串得到每个字符。
- 判断Map中是否有该键。
- 如果没有,第一次出现,存储次数为
- 打印最终结果
import java.util.HashMap;
import java.util.Scanner;
public class test
{
public static void main(String[] args) {
System.out.println("请录入一个字符串:");
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
// 定义 每个字符出现次数的方法
findChar(s);
}
private static void findChar(String line)
{
//1:创建一个集合 存储 字符 以及其出现的次数
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
//2:遍历字符串
for (int i = 0; i < line.length(); i++)
{
char c = line.charAt(i);
//判断 该字符 是否在键集中
if (!map.containsKey(c)) {
//说明这个字符没有出现过
//那就是第一次
map.put(c, 1);
} else {
//先获取之前的次数
Integer count = map.get(c);
//count++;
//再次存入 更新
map.put(c, ++count);
}
}
System.out.println(map); }
}
请录入一个字符串:
aaabbbbsda
{a=4, b=4, s=1, d=1}
2、HashMap集合
2.1HashMap介绍
HashMap是基于哈希表的Map实现的的,一个Key对应一个Value,允许使用null键和null值,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
不保证映射的顺序,特别是它不保证该顺序恒久不变!也不是同步的:
(当哈希表中的条目数超出了加载因子与当前容量的乘积时的时候,哈希表进行rehash操作(即重建内部数据结构),此时映射顺序可能会被打乱!)
2.2HashMap的存储结构(数组+链表+红黑树)
HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap 最多只允许一条记录的键为 null,允许多条记录的值为 null。
HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导致数据的不一致。如果需要满足线程安全有以下两种办法 :
- 使用Collections 的 synchronizedMap 方法使HashMap 具有线程安全的能力
- 使用 ConcurrentHashMap接口
Java7的HashMap结构:
大方向上,HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。上图中,每个绿色的实体是嵌套类 Entry 的实例,Entry 包含四个属性:key, value, hash 值和用于单向链表的next。
- capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
- loadFactor:负载因子,默认为 0.75。
- threshold:扩容的阈值,等于 capacity * loadFactor
Java8的HashMap结构:
Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成。
为什么要加入红黑树结构?
根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度为 O(n)。为了降低这部分的开销,在 Java8 中,当链表中的元素超过了 8 个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。
2.3HashMap的继承关系和API方法
HashMap的继承关系:
类 HashMap<K,V>
java.lang.Object
继承者 java.util.AbstractMap<K,V>
继承者 java.util.HashMap<K,V>
类型参数:
K - 此映射所维护的键的类型
V - 所映射值的类型
所有已实现的接口:
Serializable, Cloneable, Map<K,V>
HashMap的API:
(1)构造函数:
HashMap()
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity)
构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor)
构造一个带指定初始容量和加载因子的空 HashMap。
HashMap(Map<? extends K,? extends V> m)
构造一个映射关系与指定 Map 相同的新 HashMap。
(2)方法:
void clear()
从此映射中移除所有映射关系。
Object clone()
返回此 HashMap 实例的浅表副本:并不复制键和值本身。
boolean containsKey(Object key)
如果此映射包含对于指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
Set<Map.Entry<K,V>> entrySet()
返回此映射所包含的映射关系的 Set 视图。
V get(Object key)
返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
boolean isEmpty()
如果此映射不包含键-值映射关系,则返回 true。
Set<K> keySet()
返回此映射中所包含的键的 Set 视图。
V put(K key, V value)
在此映射中关联指定值与指定键。
void putAll(Map<? extends K,? extends V> m)
将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。
V remove(Object key)
从此映射中移除指定键的映射关系(如果存在)。
int size()
返回此映射中的键-值映射关系数。
Collection<V> values()
返回此映射所包含的值的 Collection 视图。
2.4HashMap存储自定义类型键值
练习:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到 map集合中。学生作为键, 家庭住址作为值。
注意:学生姓名相同并且年龄相同视为同一名学生。
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
class Student {
private String name;
private int age;
public Student() { }
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
//重写equals方法
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
//重写hashCode方法
public int hashCode()
{
return Objects.hash(name, age);
}
@Override
//重写toString方法
public String toString() {
return "Studen:" + name +" "+ "年龄:" +age+" ";
}
}
public class test
{
public static void main(String[] args) {
//1,创建Hashmap集合对象。
Map<Student,String>map = new HashMap<Student,String>();
//2,添加元素。
map.put(new Student("张三",28), "上海");
map.put(new Student("李四",22), "北京");
map.put(new Student("王五",24), "成都");
map.put(new Student("谢六",25), "广州");
map.put(new Student("刘强",22), "南京");
//3,取出元素。键找值方式
Set<Student>keySet = map.keySet();
for(Student key: keySet)
{
String value = map.get(key);
System.out.println(key.toString()+"来自"+value);
}
}
}
Studen:李四 年龄:22 来自北京
Studen:谢六 年龄:25 来自广州
Studen:张三 年龄:28 来自上海
Studen:刘强 年龄:22 来自南京
Studen:王五 年龄:24 来自成都
- 当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的 hashCode和equals方法。
- 如果要保证map中存放的key和取出的顺序一致,可以使用
java.util.LinkedHashMap
集合来存放。
2.5LinkedHashMap集合
我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?
在HashMap下面有一个子类 LinkedHashMap
,它是链表和哈希表组合的一个数据存储结构。
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
public class test
{
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("1", "张三");
map.put("2", "李四");
map.put("3", "王五");
//遍历键值对
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet)
{
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
1 张三
2 李四
3 王五
3、TreeMap集合
3.1TreeMap介绍
TreeMap是一个有序的key-value集合,基于红黑树(Red-Black tree)的 NavigableMap实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator进行排序,具体取决于使用的构造方法。
3.2TreeMap的继承关系和API
TreeMap的继承关系:
类 TreeMap<K,V>
java.lang.Object
继承者 java.util.AbstractMap<K,V>
继承者 java.util.TreeMap<K,V>
类型参数:
K - 此映射维护的键的类型
V - 映射值的类型
- 继承
AbstactMap
类,则TreeMap是一个Map,具体key-value特性的集合! - 实现了
Navigable
接口,意味着它支持一系列的导航方法,如有序的key返回。 - 实现了
Cloneable
接口,意味着它能被克隆。 - 实现了
Serializable
接口,意味着它支持序列化。
TreeMap的API:
1:构造方法
TreeMap()
使用键的自然顺序构造一个新的、空的树映射。
TreeMap(Comparator<? super K> comparator)
构造一个新的、空的树映射,该映射根据给定比较器进行排序。
TreeMap(Map<? extends K,? extends V> m)
构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序。
TreeMap(SortedMap<K,? extends V> m)
构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。
2:常用方法
Map.Entry<K,V> ceilingEntry(K key)
返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。
K ceilingKey(K key)
返回大于等于给定键的最小键;如果不存在这样的键,则返回 null。
void clear()
从此映射中移除所有映射关系。
Object clone()
返回此 TreeMap 实例的浅表副本。
Comparator<? super K> comparator()
返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回 null。
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射为指定值映射一个或多个键,则返回 true。
NavigableSet<K> descendingKeySet()
返回此映射中所包含键的逆序 NavigableSet 视图。
NavigableMap<K,V> descendingMap()
返回此映射中所包含映射关系的逆序视图。
Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的 Set 视图。
Map.Entry<K,V> firstEntry()
返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。
K firstKey()
返回此映射中当前第一个(最低)键。
Map.Entry<K,V> floorEntry(K key)
返回一个键-值映射关系,它与小于等于给定键的最大键关联;如果不存在这样的键,则返回 null。
K floorKey(K key)
返回小于等于给定键的最大键;如果不存在这样的键,则返回 null。
V get(Object key)
返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null。
SortedMap<K,V> headMap(K toKey)
返回此映射的部分视图,其键值严格小于 toKey。
NavigableMap<K,V> headMap(K toKey, boolean inclusive)
返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。
Map.Entry<K,V> higherEntry(K key)
返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。
K higherKey(K key)
返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。
Set<K> keySet()
返回此映射包含的键的 Set 视图。
Map.Entry<K,V> lastEntry()
返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。
K lastKey()
返回映射中当前最后一个(最高)键。
Map.Entry<K,V> lowerEntry(K key)
返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。
K lowerKey(K key)
返回严格小于给定键的最大键;如果不存在这样的键,则返回 null。
NavigableSet<K> navigableKeySet()
返回此映射中所包含键的 NavigableSet 视图。
Map.Entry<K,V> pollFirstEntry()
移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。
Map.Entry<K,V> pollLastEntry()
移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。
V put(K key, V value)
将指定值与此映射中的指定键进行关联。
void putAll(Map<? extends K,? extends V> map)
将指定映射中的所有映射关系复制到此映射中。
V remove(Object key)
如果此 TreeMap 中存在该键的映射关系,则将其删除。
int size()
返回此映射中的键-值映射关系数。
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
返回此映射的部分视图,其键的范围从 fromKey 到 toKey。
SortedMap<K,V> subMap(K fromKey, K toKey)
返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。
SortedMap<K,V> tailMap(K fromKey)
返回此映射的部分视图,其键大于等于 fromKey。
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。
Collection<V> values()
返回此映射包含的值的 Collection 视图。
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class test
{
public static void main(String[] args) {
TreeMap<Integer, String> tmap = new TreeMap<>();
tmap.put(14, "张三");
tmap.put(2, "李四");
tmap.put(32, "王五");
tmap.put(24, "刘强");
//遍历键值对
Set<Entry<Integer, String>> entrySet = tmap.entrySet();
for (Entry<Integer, String> entry : entrySet)
{
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("size of tmap is: " + tmap.size());
System.out.println("tmap contains value 张三: " + tmap.containsValue("张三"));
System.out.println("tmap contains key 32: " + tmap.containsKey(32));
System.out.println("last key in tmap is: " + tmap.lastKey());
System.out.println("key is 14 & value is " + tmap.get(14));
System.out.println("remove key 14");
tmap.remove(14);
System.out.println("tmap contains key : " + tmap.containsKey(14));
System.out.println("key in tmap:");
Iterator<Integer> iterator = tmap.keySet().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("clear tmap");
tmap.clear();
System.out.println("size of tmap: " + tmap.size());
}
}
2 李四
14 张三
24 刘强
32 王五
size of tmap is: 4
tmap contains value 张三: true
tmap contains key 32: true
last key in tmap is: 32
key is 14 & value is 张三
remove key 14
tmap contains key : false
key in tmap:
2
24
32
clear tmap
size of tmap: 0
3.3TreeMap和比较器
Java比较器TreeMap和内部比较器:
package com.zhukun;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
class Student implements Comparable{
private String name;
private int age;
public Student() { }
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
//重写equals方法
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
//重写hashCode方法
public int hashCode()
{
return Objects.hash(name, age);
}
//内部重写比较器
public int compareTo(Object o)
{
Student stu =((Student)o);
return this.age-stu.age; //按照年龄升序排序
}
@Override
//重写toString方法
public String toString() {
return "Studen:" + name +" "+ "年龄:" +age+" ";
}
}
public class test
{
public static void main(String[] args) {
Map<Student,String> map = new TreeMap<>();
//2,添加元素。
map.put(new Student("张三",28), "上海");
map.put(new Student("李四",22), "北京");
map.put(new Student("王五",24), "成都");
map.put(new Student("谢六",25), "广州");
map.put(new Student("刘强",23), "南京");
//3,取出元素。键找值方式
Set<Student>keySet = map.keySet();
for(Student key: keySet)
{
String value = map.get(key);
System.out.println(key.toString()+"来自"+value);
}
}
}
Studen:李四 年龄:22 来自北京
Studen:刘强 年龄:23 来自南京
Studen:王五 年龄:24 来自成都
Studen:谢六 年龄:25 来自广州
Studen:张三 年龄:28 来自上海
TreeMap和外部比较器:
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
class Student{
private String name;
private int age;
public Student() { }
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
//重写equals方法
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
//重写hashCode方法
public int hashCode()
{
return Objects.hash(name, age);
}
@Override
//重写toString方法
public String toString() {
return "Studen:" + name +" "+ "年龄:" +age+" ";
}
}
//外部比较器
class OutsideCompare implements Comparator{
@Override
public int compare(Object o1, Object o2)
{
Student st1 = ((Student) o1);
Student st2 = ((Student) o2);
return st1.getAge()-st2.getAge();
}
}
public class test
{
public static void main(String[] args) {
OutsideCompare com = new OutsideCompare();
Map<Student,String> map = new TreeMap<>(com);
//2,添加元素。
map.put(new Student("张三",28), "上海");
map.put(new Student("李四",22), "北京");
map.put(new Student("王五",24), "成都");
map.put(new Student("谢六",25), "广州");
map.put(new Student("刘强",23), "南京");
//3,取出元素。键找值方式
Set<Student>keySet = map.keySet();
for(Student key: keySet)
{
String value = map.get(key);
System.out.println(key.toString()+"来自"+value);
}
}
}
Studen:李四 年龄:22 来自北京
Studen:刘强 年龄:23 来自南京
Studen:王五 年龄:24 来自成都
Studen:谢六 年龄:25 来自广州
Studen:张三 年龄:28 来自上海