Java基础——集合体系Map详解
Java基础——集合体系Map详解
上文中我们理解了集合体系中的单列集合:Java基础——集合以及Java集合——Set详解,接下来呢就让阿Q带大家一起学习一下双列集合map的使用吧。
集合体系
单列集合顶层接口 遍历方式:加强for,Iterator,集合转数组Collection |-List 存取有序,元素可以重复,有序就有索引,有索引即可以通过索引操作元素。遍历方式:普通for,加强for,Iterator,ListIterator,集合转数组 |-ArrayList 不安全,效率高,数组结构:增删慢;查询快 |-LinkedList不安全,效率高,链表结构:增删快;查询慢 |-Vector 数组结构 安全 效率低 |-Set 存取无序,元素唯一。遍历方式:加强for,Iterator,集合转数组 |-HashSet 哈希算法 哈希结构 存取无序 元素唯一 |-LinkedHashSet |-TreeSet 二叉树算法可以排序双列集合Map双列集合,键唯一,值可以重复,遍历方式:根据键找值,根据键值对找键和值 |-HashMap底层的哈希结构 保证键的唯一 |-LinkedHashMap:存入和取出的顺序相同,同时键也是通过哈希算法保证元素唯一性的 |-TreeMap底层的二叉树结构 保证键的排序和唯一Map:双列集合
特点:Map双列集合,Collection是单列集合;键不可以重复,值可以重复;数据结构针对键有效。
方法:
- 增加功能:V put(K key,V value):增加元素,假如键是第一次存储,就直接存储元素,返回null;假如键不是第一次存在,就用值把以前的值替换掉,返回以前的值。
- 删除功能:void clear():移除所有的键值对元素;V remove(Object key):根据键删除键值对元素,并把值返回。
- 判断功能:boolean containsKey(Object key):判断集合能否包含指定的键;boolean containsValue(Object value):判断集合能否包含指定的值;boolean isEmpty():判断集合能否为空
- 获取功能:Set<Map.Entry<K,V>> entrySet():获取所有的键值对的集合;V get(Object key):根据键获取值;Set<K> keySet():获取集合中所有键的集合;Collection<V> values():获取集合中所有值的集合
- 长度功能:int size():返回集合中的键值对的个数
代码演示:
public static void demo1() { Map<String, Integer> map = new HashMap<>(); Integer i1 = map.put("张三", 23); //假如键是第一次存储,就直接存储元素,返回null Integer i2= map.put("李四", 24); Integer i3 = map.put("王五", 25); Integer i4 = map.put("赵六", 26); Integer i5 = map.put("张三", 26); //相同的键不存储,值覆盖,把被覆盖的值返回 System.out.println(map); //{赵六=26, 张三=26, 李四=24, 王五=25} System.out.println(i1); //null System.out.println(i2); //null System.out.println(i3); //null System.out.println(i4); //null System.out.println(i5); //23假如键不是第一次存在,就用值把以前的值替换掉,返回以前的值}public static void demo2() { Map<String, Integer> map = new HashMap<>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); Integer value = map.remove("张三"); //根据键删除元素,返回键对应的值 System.out.println(value); //23 System.out.println(map.containsKey("张三")); //false 判断能否包含传入的键 System.out.println(map.containsValue(100)); //false 判断能否包含传入的值 System.out.println(map); //{赵六=26, 李四=24, 王五=25}}public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); Collection<Integer> c = map.values(); //获取集合中所有值的集合 System.out.println(c); //[26, 23, 24, 25] System.out.println(map.size()); //4}遍历
方式一:通过keySet()获取所有键的集合,而后遍历键的集合,获取到每一个键,而后通过getKey()方法获取每一个值,这样把键和值逐个对应的找出来了,就遍历了集合。需要用到的方法:V get(Object key):根据键获取值,
Set<K> keySet():获取集合中所有键的集合。
代码演示:
public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); //获取所有的键 /* Set<String> keySet = map.keySet(); //获取所有键的集合 Iterator<String> it = keySet.iterator(); //获取迭代器 while(it.hasNext()) { //判断集合中能否有元素 String key = it.next(); //获取每一个键 Integer value = map.get(key); //根据键获取值 System.out.println(key + "=" + value); } */ //使用加强for循环遍历 for(String key : map.keySet()) { //map.keySet()是所有键的集合 System.out.println(key + "=" + map.get(key)); }}方式二:通过entrySet()获取所有的键值对的集合,而后遍历键值对的集合,获取每一个键值对,而后根据键值对来获取每一个键和值,这样把键和值逐个对应的找出来了,就遍历了集合。需要用到的方法:Set<Map.Entry<K,V>> entrySet():获取所有的键值对的集合,Map.Entry接口里面的K getKey():获取键值对中的键,V getValue():获取键值对中的值。
代码演示:
public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); //Map.Entry说明Entry是Map的内部接口,将键和值的键值对封装成了Entry对象,并存储在Set集合中 /* Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); //获取每一个 键值对 对象 Iterator<Map.Entry<String, Integer>> it = entrySet.iterator(); while(it.hasNext()) { //获取每一个键值对对象 Map.Entry<String, Integer> en = it.next(); //父类引用指向子类对象 //Entry<String, Integer> en = it.next(); //直接获取的是子类对象 String key = en.getKey(); //根据键值对对象获取键 Integer value = en.getValue(); //根据键值对对象获取值 System.out.println(key + "=" + value); } */ for(Entry<String, Integer> en : map.entrySet()) { System.out.println(en.getKey() + "=" + en.getValue()); }}Map.Entry原理:Entry是Map接口里面的一个内部接口, 他的实现类是Map子类里面的一个静态的内部类
HashMap
键是如何保证唯一性的呢? 通过哈希算法。 HashSet底层就是通过HashMap的键来完成的,所以说HashMap保证键的唯一性必需要让键的元素所在的类去重写 hashCode()和 equals()方法。
代码演示:
public static void main(String[] args) { HashMap<Student, String> hm = new HashMap<>(); //Student作为键,必需重写equals和hashCode() 才能让HashMap保证键的唯一 hm.put(new Student("张三", 23), "北京"); hm.put(new Student("张三", 23), "上海"); hm.put(new Student("李四", 24), "广州"); hm.put(new Student("王五", 25), "深圳"); System.out.println(hm); //{Student [name=张三, age=23]=上海, Student [name=李四, age=24]=广州, Student [name=王五, age=25]=深圳} 去掉了重复的 "张三", 23} public class Student{ //重写了equals和HashCode的 Student类 private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int hashCode() { //重写hashCode方法 final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { //重写equals方法 if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }}LinkedHashMap
存入和取出的顺序相同,同时键也是通过哈希算法保证元素唯一性的。
public static void main(String[] args) { LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>(); lhm.put("张三", 23); lhm.put("李四", 24); lhm.put("赵六", 26); lhm.put("王五", 25); System.out.println(lhm);//{张三=23, 李四=24, 赵六=26, 王五=25} 存取有序}TreeMap
键是如何保证排序和唯一的呢?通过二叉树算法,TreeSet的底层就是通过TreeMap的键来完成的。
方式一:所以TreeMap保证键的唯一和排序需要让 TreeMap的键的元素所在的类去实现自然排序Comparable接口;
方式二:TreeMap保证键的唯一和排序 需要调用TreeMap的有参构造,传入一个比较器 Comparator
代码演示:
public static void main(String[] args) { TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() { //用TreeMap的有参构造方法 传入比较器 @Override public int compare(Student s1, Student s2) { int num = s1.getName().compareTo(s2.getName()); //按照姓名比较 return num == 0 ? s1.getAge() - s2.getAge() : num; } }); tm.put(new Student("张三", 23), "北京"); tm.put(new Student("李四", 13), "上海"); tm.put(new Student("赵六", 43), "深圳"); tm.put(new Student("王五", 33), "广州"); System.out.println(tm); }? public static void demo1() {? TreeMap<Student, String> tm = new TreeMap<>(); //用TreeMap的无参构造方法创立的对象? //Student作为键,必需让Student实现Comparable接口 并且重写CompareTo方法 tm.put(new Student("张三", 23), "北京"); ? tm.put(new Student("李四", 13), "上海");? tm.put(new Student("王五", 33), "广州");? tm.put(new Student("赵六", 43), "深圳");? ? System.out.println(tm);? } //Student实现了Comparable接口 重写了CompareTo方法? public class Student implements Comparable<Student> { ? private String name;? private int age;? public Student() {? super(); ? }? public Student(String name, int age) {? super();? this.name = name;? this.age = age;? }? ? @Override? public int compareTo(Student o) { // 重写了CompareTo方法? int num = this.age - o.age; //以年龄为主要条件? return num == 0 ? this.name.compareTo(o.name) : num;? }? }HashMap的嵌套
学校一年级学生HashMap 键:一年级对象HashMap 值:班号1 键:学生对象 值:归属地 键:学生对象 值:归属地 键:一年级对象HashMap 值:班号2 键:学生对象 值:归属地 键:学生对象 值:归属地代码演示:
public static void main(String[] args) { //定义一年级1班 HashMap<Student, String> hm1 = new HashMap<>(); hm1.put(new Student("张三", 23), "北京"); hm1.put(new Student("李四", 24), "北京"); hm1.put(new Student("王五", 25), "上海"); hm1.put(new Student("赵六", 26), "广州"); //定义一年级2班 HashMap<Student, String> hm2 = new HashMap<>(); hm2.put(new Student("唐僧", 1023), "北京"); hm2.put(new Student("孙悟空",1024), "北京"); hm2.put(new Student("猪八戒",1025), "上海"); hm2.put(new Student("沙和尚",1026), "广州"); //定义双元课堂 HashMap<HashMap<Student, String>, String> hm = new HashMap<>(); hm.put(hm1, "一年级1班"); hm.put(hm2, "一年级2班"); //遍历双列集合 for(HashMap<Student, String> h : hm.keySet()) { //hm.keySet()代表的是一年级所有的班级集合 h是每个班级 String value = hm.get(h); //get(h)根据班级对象获取班级代号value //遍历键的双列集合对象 for(Student key : h.keySet()) { //h.keySet()代表班级中所有的学生对象集合,key是每个学生 String value2 = h.get(key); // h.get(key) 根据学生对象找到学生的所在地value2 System.out.println(key + "=" + value2 + "=" + value); } }}HashMap和Hashtable
1:HashMap线程不安全,效率高,1.2出现的;Hashtable线程安全的,效率低,1.0出现的。
2:HashMap可以存null键或者null值,Hashtable不可以存储null键或者null值。
代码演示:
public static void main(String[] args) { HashMap<String, Integer> hm = new HashMap<>(); hm.put(null, 23); //不报错 hm.put("李四", null); //不报错 System.out.println(hm); //{null=23, 李四=null} /* Hashtable<String, Integer> ht = new Hashtable<>(); ht.put(null, 23); //编译不报错,运行报错java.lang.NullPointerException ht.put("张三", null); //编译不报错,运行报错java.lang.NullPointerException System.out.println(ht); */}Collections
public static <T extends Comparable<? super T>> void sort(List<T> list);排序:只能给List排序,而且要求被排序的List集合里面存储的元素必需实现Comparable接口(对象只有实现了Comparable接口,才能说明对象具有比较性)
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key);在已经排好序的list集合中查找key的索引,List集合中的元素必需实现Comparable接口
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);给求Collection集合中最大的元素,Collection集合的元素必需实现了Comparable接口,由于假如元素不具有比较性 我如何知道谁最大呢?
public static void reverse(List<?> list);把list集合反转,list集合里面的元素没有任何要求
public static void shuffle(List<?> list);把list集合里面的元素打乱顺序,list集合里面的元素没有任何要求
代码演示:
public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("c"); list.add("d"); list.add("g"); list.add("f"); //String类实现了Comparable接口重写了CompareTo方法,所以可以求最大值 //根据list集合存的元素里面的CompareTo方法的比较规则 获取集合中的最大值 System.out.println(Collections.max(list));//g Collections.reverse(list); //反转集合 Collections.shuffle(list); //随机置换,可以用来洗牌 System.out.println(list); //[g, f, d, a, c]}public static void demo() { ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("c"); list.add("d"); list.add("f"); list.add("g"); Collections.sort(list); //进行二分法查找之前,必需先把list集合排序 System.out.println(Collections.binarySearch(list, "c")); //1 System.out.println(Collections.binarySearch(list, "b")); //-2}好了集合的一律内容就先总结到这了,以后假如遇到什么问题再继续升级。想理解更多学习知识,请关注微信公众号“阿Q说”,获取更多学习资料吧!你也可以后端留言说出你的疑惑,阿Q将会在后期的文章中为你解答。每天学习一点点,每天进步一点点。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Java基础——集合体系Map详解