Map(键值对、键唯一、值不唯一)
核心: Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
l Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
l Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
l Collection中的集合称为单列集合,Map中的集合称为双列集合。
l 需要注意:
Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
. Map集合中包含HashMap(怎么存不一定怎么取)和LinkHahMap(怎么存就怎么取)
HashMap
数组方式存储key/value,线程非安全,允许null作为key和value,key不可以重复,value允许重复,不保证元素迭代顺序是按照插入时的顺序,key的hash值是先计算key的hashcode值,然后再进行计算,每次容量扩容会重新计算所以key的hash值,会消耗资源,要求key必须重写equals和hashcode方法
.HashMap<K,V>(泛型:键,值):存取数据才有的哈希表结果,元素怎么存不一定怎么取,由于要保证键的唯一不重复,需要重写键的hashcode()和equals()方法
默认初始容量16,加载因子0.75,扩容为旧容量乘2,查找元素快,如果key一样则比较value,如果value不一样,则按照链表结构存储value,就是一个key后面有多个value;
方法
1、添加:
V 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
4、长度:
Int size()
Hashtable
Hashtable与HashMap类似,是HashMap的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。
LinkedHashMap
LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候会比HashMap慢,有HashMap的全部特性
Entry键值对对象Map.Entry<K,V>
思路
- 获取集合中所有的键值对(Entry)对象,返回Set
2.遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象
3.通过键值对(Entry)对象,获取Entry中的键与值
getKey() 返回Entry对象中的键
getValue() 返回Entry对象中的值
entrySet() 用于返回Map集合中所有的键值对(Entry)对象,以Set集合形式返回
遍历
核心思想:利用key键关联
第一种:KeySet()
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取key 。
取到的结果会乱序,是因为取得数据行主键的时候,使用了HashMap.keySet()方法,而这个方法返回的Set结果,里面的数据是乱序排放的。
代码展示:
package com.oracle.Demo01; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class demo01 { public static void main(String[] args) //创建map集合 Map<String,String> mp= new HashMap<String,String>(); /*向map存值:map.put("","");Map集合的取值方式:map.get(key) */ mp.put("a", "123"); mp.put("adin", "1234"); mp.put("b", "789"); /* mp.put("a", "147");重复数据,key存不进去,但value值会覆盖掉,map不能存重复值的键,如果存了重复键,那么后来键对应的值会覆盖前面键的值,但是值可以重复存入,一个键只能对应一个值*/ // System.out.println(mp.get("a")); /*遍历 。遍历不能用增强for:因为Map集合的泛型有俩,不知道遍历哪一个; *不能用迭代器:因为Map集合没有迭代器对象,迭代器只存在于Collection集合中;不能用普通for:因为没有下标*/ //只能用 keyset+增强for的方法 /*思路是:通过增强for遍历key所在的集合,得到每一个key再通过map.get(key)的方式找到key所对应的value的值*/ //首先获取key所在的set集合 Set<String> set=mp.keySet(); //然后增强for遍历set集合 for(String k: set) { //get取值 System.out.println(k+"..."+mp.get(k)); } //keyset+iterator //获取所有key所在的set集合 Set<String> set2=mp.keySet(); //获取迭代器对象,泛型就写和key一样的类型 Iterator<String> it=set2.iterator(); while(it.hasNext()) { //接值返回,获取值,遍历key String key=it.next(); System.out.println(key+".."+mp.get(key)); /*//因为迭代器是一直向后走,*不能往前走,所以外面得顶一个变量接一下,然后遍历这个变量 */ } } }
entrySet()
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。(一个关系就是一个键-值对),就是把(key-value)作为一个整体一对一对地存放到Set集合当中的。Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()两种方法来取key和value。返回的是Entry接口。
package com.oracle.Demo01; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class demo02 { public static void main(String[] args) { Map<Integer,String>map=new HashMap<Integer,String>(); map.put(1, "英短"); map.put(2, "三花"); map.put(3, "乌龙"); //entryset+增强for //获取所有结婚对象 Set<Map.Entry<Integer,String>> set=map.entrySet(); /*这里的entry是map类的成员内部类,通过外部成员名.内部成员名<>的方式调用 这里是把map的所有的键和值都封装成一个个的entry对象,在把这些entry对象存到一个Set集合里面, 然后通过增强for遍历set集合里的每一个entry对象,*/ //2.遍历 增强for遍历set集合里的每一个entry对象 for(Map.Entry<Integer,String> entry:set) { /*这里的增强for的泛型 就写set里的泛型就是map的entry对象,得到每个entry对象后再定义向下类型的变量来接收key和value值,通过entry.getkey()得键,entry.getvalue()得值 */ int key=entry.getKey(); String value=entry.getValue(); System.out.println(key+".."+value); } //迭代器遍历 /*在定义完map集合并把entry对象赋值到Set集合后,定义迭代器对象Iterator<Map.entry<String,String>> it=set.iterator;这里泛型和set的一样,获取到 **/ //enttryset+Inteator 遍历这里定义个entry对象接收it.next()遍历后得到的entry对象,然后通过 entry.getkey()得键;entry.getvalue()得值*/ //集合获取每一个entry对象 Set<Map.Entry<Integer,String>> set2=map.entrySet(); //获取迭代器对象 Iterator<Map.Entry<Integer,String>> it=set2.iterator(); //循环遍历 while(it.hasNext()){ Map.Entry<Integer,String> entry=it.next(); int key =entry.getKey(); String value=entry.getValue(); System.out.println(key+"...."+value); } } }
HashMap存储自定义类型键值
package com.oracle.Demo01; import java.util.HashMap; import java.util.Map; import java.util.Set; public class demo03 { public static void main(String[] args) { Map<Person,String> map=new HashMap<Person,String>(); //如果key存的是重复值那么就需要要自定义类里面重写Equals方法和hascode方法,如果是值那么就不用了,因为可以存重复值 map.put(键,值, ); map.put(new Person("大咪",12), "java0611"); map.put(new Person("小咪",10), "java0611"); map.put(new Person("大咪",12), "java0611"); // //遍历; //通过增强for得到每一个key值然后通过.get()方法得到value值 Set<Person> set=map.keySet(); for(Person p:set) { System.out.println(p+".."+map.get(p)); /* Person [name=大咪, age=12]..java0611 *Person [name=小咪, age=10]..java0611*/ }
遍历的方式有两种,
1.通过keyset()方法把key值都存到一个Set集合里面;
再通过增强for(通过得到的key值,在用.get(key)方法得到value值
2.通过keyset()方法把key值都存到一个set的集合里面用过迭代器(itaretor)得到每一个key值,再通过.get(key)方法得到value值
entry()方法遍历:
通过.entry()方法得到set集合对象把map里的每一对key和value封装成一个对象,通过变量对象后用.getkey()和.getvalue()方法来得到值,
1.增强for遍历:for(对象的类型<> 变量名:对象所在的set集合)得到每一个set封装的enty对象;通过entry对象.getkey()和.getvalue()方法得到相应的值然后打印;
2.通过迭代器遍历:把Map中的每一个entry对象封装到Set集合里面,定义迭代器对象,泛型是entry对象,再用while进行遍历,得到的it.next()
实际上就是entry对象,再通过.getkey()和.getvalue()得到相应的key和value
}
}
静态导入与可变参数:
我们知道在写java类的时候通常需要导入需要的包,例如“import java.util.ArrayList”。实际上也可以不导包而在使用的使用直接写上类的完整路径,如“java.util.ArrayList al = new java.util.ArrayList();”,但这样写的话语句太长了并且影响代码的阅读性。所以,import导包可以很好的解决这两个问题。
静态导入格式:
import static XXX.YYY; 导入后YYY可直接使用。
package com.oracle.Demo02; import static java.lang.System.out; public class deno01 { public static void main(String[] args) { //导入静态类 out.println("helloword"); out.println(add(1,2)); out.println(add(1,2,8)); } //写一个方法,计算求和 //可变参数 相当于一个int[]a, public static int add( int ...a) { int sum=0; for(int s:a) { sum+=s; } return sum; } }
(在第一行)导入了System类下的所有静态变量和静态方法,因此在使用的时候在需要写"System."的地方可以省略。
再来看看静态导入和一般导入的写法的不同之处:
☆) 和一般导入相比,静态导入时 import 后面要写"static" 关键字
类似的能使用到静态的导入的地方有Math、Collections、Arrays等等。
l 可变参数:add方法在同一个类中,只能存在一个。因为会发生调用的不确定性
注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置,固定参数放在首位。
Collections集合工具类
package com.oracle.Demo02; import java.util.ArrayList; import java.util.Collections; public class demo02 { public static void main(String[] args) { ArrayList<String> arr=new ArrayList<String>(); arr.add("a"); arr.add("b"); arr.add("c"); //打乱顺序 Collections.shuffle(arr); System.out.println(arr);//[b, a, c] //排序 Collections.sort(arr);; System.out.println(arr);//[a, b, c] } }