简单看下Map的场景
如果程序中存储了几百万个学生,而且经常需要使用学号来搜索某个学生,那么这个需求有效的数据结构就是Map。
Map是一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是整数。
在Map中键(key)可以使任意类型的对象。
Map中不能有重复的键(Key),每个键(key)都有一个对应的值(value)。
一个键(key)和它对应的值构成map集合中的一个元素。
Map中的元素是两个对象,一个对象作为键,一个对象作为值。键不可以重复,但是值可以重复。
看顶层共性方法找子类特有对象.
Map与Collection在集合框架中属并列存在
Map存储的是键值对
Map存储元素使用put()
方法,Collection使用add()
方法
Map集合没有直接取出元素的方法,而是先转成Set
集合,在通过迭代获取元素
Map集合中键要保证唯一性
也就是Collection是单列集合, Map 是双列集合。
总结:
Map一次存一对元素, Collection 一次存一个。
Map 的键不能重复,保证唯一。
Map 一次存入一对元素,是以键值对的形式存在.键与值存在映射关系.一定要保证键的唯一性.
查看api文档:
interface Map<K,V>
K - 此映射所维护的键的类型
V - 映射值的类型
概念
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
特点
Key和Value是1对1的关系,如:门牌号 :家 老公:老婆
双列集合
Map体系
| Map 接口 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
---|Hashtable:
底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。
效率较低,被HashMap 替代。
---|HashMap:
采用哈希表实现,所以无序。
底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。
要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
---| LinkedHashMap:
该子类基于哈希表又融入了链表。可以Map集合进行增删提高效率。
---|TreeMap:
底层是二叉树数据结构,可以对健进行排序。
可以对map集合中的键进行排序。
需要使用Comparable或者Comparator 进行比较排序。
return 0,来判断键的唯一性。
常见方法
1、添加:
put(K key, V value) (可以相同的key值,但是添加的value值会覆盖前面的,返回值是前一个,如果没有就返回null)
putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。
2、删除
remove() 删除关联对象,指定key对象
clear() 清空集合对象
3、获取
value get(key); 可以用于判断键是否存在的情况。当指定的键不存在的时候,返回的是null。
4、判断:
boolean isEmpty() 长度为0返回true否则false
boolean containsKey(Object key) 判断集合中是否包含指定的key
boolean containsValue(Object value) 判断集合中是否包含指定的value
int size()获取长度
基本操作案例:
// Map集合包
import java.util.Map;
import java.util.HashMap;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
//---------------------- 新增 ----------------------
// 定义一个Map的容器对象
Map map1 = new HashMap();
// 添加重复的键值(值不同),会返回最后覆盖的值
map1.put("jack", 20);
map1.put("rose", 18);
map1.put("lucy", 17);
map1.put("jack", 25);
System.out.println(map1);
// 定义一个Map的容器对象
Map map2= new HashMap();
map2.put("张三丰", 100);
map2.put("虚竹", 20);
// 从指定映射中将所有映射关系复制到此映射中。
map1.putAll(map2);
System.out.println(map1);
//---------------------- 删除 ----------------------
// 指定key删除,返回删除的键值对映射的值。
System.out.println("value:" + map1.remove("jack"));
// 直接整个清空
map2.clear();
System.out.println("map2:" + map2);
//---------------------- 获取 ----------------------
// 指定key读取
System.out.println("value:" + map1.get("虚竹"));
// 获取长度
System.out.println("map1长度:" + map1.size());
//---------------------- 判断 ----------------------
// 是否空Map
System.out.println("Map1是否空:" + map1.isEmpty());
// 键是否存在
System.out.println("Map1键是否存在:" + map1.containsKey("jack"));
// 值是否存在
System.out.println("Map1值是否存在:" + map1.containsValue(100));
}
}
1.HashMap
遍历读取Map
Map的遍历读取主要有三种方法:
1、将map 集合中所有的键取出存入set集合。
keySet() 返回所有的key对象的Set集合,再通过get方法获取键对应的值。
2、values() 获取所有的值,不能获取到key对象
3、Map.Entry对象【推荐使用,重点】
entrySet() 将map 集合中的键值映射关系打包成一个对象。
Map.Entry对象通过Map.Entry对象的getKey,getValue获取其键和值。
第一种遍历方法:keySet()
将Map转成Set集合keySet()
,通过Set的迭代器取出Set集合中的每一个元素(Iterator)就是Map集合中的所有的键,再通过get方法获取键对应的值。
// Map集合包
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
// 定义一个Map的容器对象
Map map = new HashMap();
// 添加重复的键值(值不同),会返回最后覆盖的值
map.put("jack", 20);
map.put("rose", 18);
map.put("lucy", 17);
map.put("java", 25);
// 先转Set
Set<String> ks = map.keySet();
Iterator<String> it = ks.iterator();
// 不为空
while (it.hasNext()) {
// 获取key
String key = it.next();
// 因为不知道value的类型,所以用obj是通用
Object value = map.get(key);
// 也可以强行转成自己知道的类型
//Integer value = (Integer) map.get(key);
System.out.println(key+":"+value);
}
}
}
第二种遍历方法: 通过values(),获取所有值,不能获取到key对象
// Map集合包
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
// 定义一个Map的容器对象
Map map = new HashMap();
// 添加重复的键值(值不同),会返回最后覆盖的值
map.put("jack", 20);
map.put("rose", 18);
map.put("lucy", 17);
map.put("java", 25);
Collection vs = map.values();
Iterator<Integer> it = vs.iterator();
// 有内容
while(it.hasNext()){
// 拿Value
Integer value = it.next();
System.out.println(+value);
}
}
}
第三种遍历方法:Map.Entry()
// Map集合包
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
// 定义一个Map的容器对象
Map map = new HashMap();
// 添加重复的键值(值不同),会返回最后覆盖的值
map.put("jack", 20);
map.put("rose", 18);
map.put("lucy", 17);
map.put("java", 25);
// 转Set
Iterator<Map.Entry> entries = map.entrySet().iterator();
// 有内容
while(entries.hasNext()){
// 拿当前的
Map.Entry<String, Integer> entry = entries.next();
// 拿Key
String key = entry.getKey();
// 拿Value
Integer value = entry.getValue();
System.out.println(key+':'+value);
}
}
}
最后一个常用的遍历方法:
// Map集合包
import java.util.Map;
import java.util.HashMap;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
// 定义一个Map的容器对象
Map<String, Integer> map = new HashMap();
map.put("jack", 20);
map.put("rose", 18);
map.put("lucy", 17);
map.put("java", 25);
// 上面的Map类型必须定义,不然找不到Map类型
for(Map.Entry<String, Integer> entry : map.entrySet()){
// 拿key
String key = entry.getKey();
// 拿value
Integer value = entry.getValue();
System.out.println(key+":"+value);
}
}
}
2.TreeMap
TreeMap的排序,TreeMap可以对集合中的键进行排序。
如何实现键的排序?
方式一:元素自身具备比较性
和TreeSet一样原理,需要让存储在键位置的对象实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。
方式二:容器具备比较性
当元素自身不具备比较性,或者自身具备的比较性不是所需要的。
那么此时可以让容器自身具备。
需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。
注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;
注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。
(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,以为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)
通过return 0
来判断唯一性。
基本操作汇总
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
//创建TreeMap对象:
TreeMap<String,Integer> treeMap = new TreeMap<String,Integer>();
System.out.println("初始化后,TreeMap元素个数为:" + treeMap.size());
//新增元素:
treeMap.put("hello",1);
treeMap.put("world",2);
treeMap.put("my",3);
treeMap.put("name",4);
treeMap.put("is",5);
treeMap.put("jiaboyan",6);
treeMap.put("i",6);
treeMap.put("am",6);
treeMap.put("a",6);
treeMap.put("developer",6);
System.out.println("添加元素后,TreeMap元素个数为:" + treeMap.size());
//遍历元素:
Set<Map.Entry<String,Integer>> entrySet = treeMap.entrySet();
for(Map.Entry<String,Integer> entry : entrySet){
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("TreeMap元素的key:"+key+",value:"+value);
}
//获取所有的key:
Set<String> keySet = treeMap.keySet();
for(String strKey:keySet){
System.out.println("TreeMap集合中的key:"+strKey);
}
//获取所有的value:
Collection<Integer> valueList = treeMap.values();
for(Integer intValue:valueList){
System.out.println("TreeMap集合中的value:" + intValue);
}
//获取元素:
Integer getValue = treeMap.get("jiaboyan");//获取集合内元素key为"jiaboyan"的值
String firstKey = treeMap.firstKey();//获取集合内第一个元素
String lastKey =treeMap.lastKey();//获取集合内最后一个元素
String lowerKey =treeMap.lowerKey("jiaboyan");//获取集合内的key小于"jiaboyan"的key
String ceilingKey =treeMap.ceilingKey("jiaboyan");//获取集合内的key大于等于"jiaboyan"的key
SortedMap<String,Integer> sortedMap =treeMap.subMap("a","my");//获取集合的key从"a"到"jiaboyan"的元素
//删除元素:
Integer removeValue = treeMap.remove("jiaboyan");//删除集合中key为"jiaboyan"的元素
treeMap.clear(); //清空集合元素:
//判断方法:
boolean isEmpty = treeMap.isEmpty();//判断集合是否为空
boolean isContain = treeMap.containsKey("jiaboyan");//判断集合的key中是否包含"jiaboyan"
}
}
使用元素自然排序
import java.util.TreeMap;
public class HelloWorld{
// 入口
public static void main(String[] agrs) {
TreeMap<Integer,String> treeMap = new TreeMap<Integer, String>();
treeMap.put(1,"jiaboyan");
treeMap.put(6,"jiaboyan");
treeMap.put(3,"jiaboyan");
treeMap.put(10,"jiaboyan");
treeMap.put(7,"jiaboyan");
treeMap.put(13,"jiaboyan");
System.out.println(treeMap.toString());
}
}
使用自定义比较器排序
import java.util.Comparator;
import java.util.TreeMap;
class SortedTest {
private int age;
public SortedTest(int age){
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class SortedTestComparator implements Comparator<SortedTest> {
//自定义比较器:实现compare(T o1,T o2)方法:
public int compare(SortedTest sortedTest1, SortedTest sortedTest2) {
int num = sortedTest1.getAge() - sortedTest2.getAge();
if(num==0){//为0时候,两者相同:
return 0;
}else if(num>0){//大于0时,后面的参数小:
return 1;
}else{//小于0时,前面的参数小:
return -1;
}
}
}
public class HelloWorld {
public static void main(String[] agrs){
//自定义顺序比较
customSort();
}
//自定义排序顺序:
public static void customSort(){
TreeMap<SortedTest,String> treeMap = new TreeMap<SortedTest, String>(new SortedTestComparator());
treeMap.put(new SortedTest(10),"hello");
treeMap.put(new SortedTest(21),"my");
treeMap.put(new SortedTest(15),"name");
treeMap.put(new SortedTest(2),"is");
treeMap.put(new SortedTest(1),"jiaboyan");
treeMap.put(new SortedTest(7),"world");
System.out.println(treeMap.toString());
}
}
这个自定义排序太难了,说实在的我也没搞明白,以后有收获再回头补上吧