Map集合继承结构
目录
🥅Map集合概述
🥅Map接口常用的方法
🥅哈希表(散列表)数据结构
🥅同时重写HashCode和equals
🥅HashMap和Hashtable的区别
🥅Properties类
🥅TreeSet(TreeMap)集合
🥅自平衡二叉树数据结构
🥅实现比较器接口
🥅集合工具类Collections
🥅Map集合概述
(1)Map和Collection没有继承关系。
(2)Map集合以key和value的方式存储数据:
键值对key和value都是引用数据类型。
key和value都是存储对象的内存地址。
key起到主导的地位,value是key的一个附属品。
(3)HashMap: 底层是哈希表。
(4)HashTable: 底层也是哈希表,只不过线程是安全的,效率较低使用较少。
(5)Prorerties:线程是安全的,并且key和value只能储存字符串String类型。
(6)TreeMap:底层是二叉树,TreeMap集合的key可以自动按照大小顺序排序。
⭐️Map集合继承结构图
🥅Map接口常用的方法
Map接口中常用方法:
V put(K key, V value) 向Map集合中添加键值对
V get(Object key) 通过key获取value
void clear() 清空Map集合
boolean containsKey(Object key) 判断Map中是否包含某个key
boolean containsValue(Object value) 判断Map中是否包含某个value
boolean isEmpty() 判断Map集合中元素个数是否为0
V remove(Object key) 通过key删除键值对
int size() 获取Map集合中键值对的个数。
Collection values() 获取Map集合中所有的value(所有的values是一个Collection集合)
Set keySet() 获取Map集合所有的key(所有的键(Key)是一个Set集合)
Set<Map.Entry> entrySet() 将Map集合转换成Set集合
对于Map结合转换成Set集合怎么理解?假设现在有一个Map集合,如下所示:
map1集合对象
key value ---------------------------- 1 zhangsan 2 lisi 3 wangwu 4 zhaoliu
Set set = map1.entrySet();
set集合对象的形式,把Map集合的两个值通过=的方式撮合成一个了
1=zhangsan 2=lisi 3=wangwu 4=zhaoliu
注意:Map集合通过entrySet()方法转换成的这个Set集合,Set集合中元素的类型是 Map.Entry;Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态内部类
⭐️回顾静态内部类
package com.bjpowernode.javase.map;public class Myclass { //声明一个静态内部类 public static class InnerClass{ // 静态内部类的静态方法 public static void m1(){ System.out.println("静态内部类的静态方法执行!"); } // 静态内部类的实例方法 public void m2(){ System.out.println("静态内部类的实例方法执行!"); } } public static void main(String[] args) { // 静态方法执行,类名:Myclass.InnerClass Myclass.InnerClass.m1(); // 创建静态内部类对象 Myclass.InnerClass mi = new Myclass.InnerClass(); mi.m2(); //执行 //给一个Set集合;改Set集合中存储的对象是:MyClass.InnerClass类型 Set set = new HashSet(); }}
⭐️例1:
package com.bjpowernode.javase.map;import java.util.Collection;import java.util.HashMap;import java.util.Map;public class MapTest02 { public static void main(String[] args) { // 创建Map集合对象 Map map = new HashMap(); // 1、向Map集合中添加键值对;put方法 map.put(1,"张三"); // 1是自动装箱 map.put(2,"李四"); map.put(3,"王五"); // 2、通过key获取value;get方法 String str = map.get(1); System.out.println(str); //张三 // 3、获取Map集合中键值对的个数;size方法 System.out.println(map.size()); //3 // 4、 通过key删除键值对;remove方法 map.remove(1); System.out.println(map.size()); //2 // contains方法底层调用的都是equals进行比对的,所以自定义的类型需要重写equals方法。 // 5、判断Map中是否包含某个key;containsKey方法 boolean b1 = map.containsKey(2); System.out.println(b1); // true // 6、判断Map中是否包含某个value;containsValue方法 boolean b2 = map.containsValue("李四"); System.out.println(b2); // true // 7、获取所有的value;values方法 Collection c = map.values(); // 遍历打印这个集合 for(String s:c){ //增加for循环进行打印 System.out.println(s); } // 8、清空集合;clear方法 map.clear(); System.out.println(map.size()); //0 // 9、判断Map集合是否为空;isEmpty方法 System.out.println(map.isEmpty()); // true }}
⭐️例2:遍历Map结合(重点)
package com.bjpowernode.javase.map;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;// Map集合遍历public class MapTest03 { public static void main(String[] args) { //第一种方式:获取所有的key,通过遍历key,来遍历value Map map = new HashMap(); map.put(1, "zhangsan"); map.put(2, "lisi"); map.put(3, "wangwu"); // 先获取所有的key,所有的key是一个Set集合 Set keys = map.keySet(); // 在遍历key,通过key获取value // 方法1:利用迭代器 Iterator it = keys.iterator(); while (it.hasNext()){ Integer key = it.next(); //获取其中一个key String value = map.get(key); //通过key获取value System.out.println(key+"="+value); } // 方法2:foreach for(Integer key:keys){ System.out.println(key+"="+map.get(key)); } //第二种方式: Set<Map.Entry> entrySet() 将Map集合转换成Set集合 Set<Map.Entry> set = map.entrySet(); // 方法1:使用迭代器进行打印 Iterator<Map.Entry> it2 = set.iterator(); while(it2.hasNext()){ Map.Entry node = it2.next(); //取出一个节点 Integer key = node.getKey(); //取出节点的key String value = node.getValue(); //取出节点的value System.out.println(key+"="+value); } // 方法2:foreach方式 // 这种方式效率比较高,因为获取key和value都是直接从node对象中获取的属性值。 // 这种方式比较适合于大数据量。 for( Map.Entry node:set){ System.out.println(node.getKey()+"="+node.getValue()); } }}
🥅哈希表(散列表)数据结构
1、HashMap集合底层是哈希表/散列表的数据结构。
2、哈希表是一个怎样的数据结构呢?
哈希表是一个数组和单向链表的结合体。
数组:在查询方面效率很高,随机增删方面效率很低。
单向链表:在随机增删方面效率较高,在查询方面效率很低。
哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。
3、HashMap集合底层的源代码:
public class HashMap{ // HashMap底层实际上就是一个数组。(一维数组) Node[] table; // 静态的内部类HashMap.Node static class Node { final int hash; // 哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法,可以转换存储成数组的下标。) final K key; // 存储到Map集合中的那个key V value; // 存储到Map集合中的那个value Node next; // 下一个节点的内存地址。 } }
哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表。(数组和链表的结合体。)
4、最主要掌握的是:
map.put(k,v)实现原理:
第一步:先将k,v封装到Node对象当中
第二步:底层会调用k的hashCode()方法得出hash值
然后通过哈希函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素;就把Node添加到这个位置上;如果下标对应的位置上有链表,此时会拿着k和链表上每一个结点的k进行equals比较,如果所有的equals方法返回的都是false,那么将这个新结点添加到链表的结尾如果其中一个equals返回了true,那么这个结点的value将会被覆盖
v = map.get(k)实现原理:
先调用k的hashCode()方法得出哈希值,通过哈希算法转换成数组下标;通过数组下标快速定位到某个位置上,如果这个位置上什么都没有,返回null;如果这个位置上有单链表,那么会拿着参数k和单链表上的每个结点中的k进行equals;如果所有的equals方法返回的都是false,那么get方法返回null;只要其中一个结点的k和参数k在equals的时候返回true,那么此时这个结点的value就是我们要找的value,get方法最终返回这个要找的value
重点:通过上面的讲解可以得出HashMap集合的key,会先后调用两个方法, 一个方法是hashCode(),一个方法是equals(),这两个方法都需要重写
注意:同一个单向链表上所有节点的hash值相同,因为他们的数组下标是一样的但同一个链表上k和k的equals方法肯定返回的是false,都不相同(无序不可重复)
5、HashMap集合的key部分特点:无序,不可重复。
为什么无序? 因为不一定挂到哪个单向链表上。
不可重复是怎么保证的? equals方法来保证HashMap集合的key不可重复。
如果key重复了,value会覆盖。
放在HashMap集合key部分的元素其实就是放到HashSet集合中了。
所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法。6、哈希表HashMap使用不当时无法发挥性能!(我们考虑两个极端情况)
假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成了
纯单向链表。这种情况我们成为:散列分布不均匀。
什么是散列分布均匀?
假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的,
是散列分布均匀的。
假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题?
不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。
也是散列分布不均匀。
所以要想散列分布均匀,需要你重写hashCode()方法时有一定的技巧。
7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法。
8、HashMap集合的默认初始化容量是16,默认加载因子是0.75扩容:扩容后的容量是原容量的2倍
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容。
重点,记住:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的,
这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。
package com.bjpowernode.javase.map;import java.util.HashMap;import java.util.Map;import java.util.Set;public class HashMapTest01 { public static void main(String[] args) { // 测试HashMap 集合key部分的元素特点 // Integer是key,它的hashCode和equals都重写了 Map map = new HashMap(); map.put(111,"zhangsan"); map.put(222,"lisi"); map.put(333,"wangwu"); map.put(333,"zhaoliu"); //key重复,value会覆盖上面的值 // 元素个数 System.out.println(map.size()); //3 // 遍历 Set<Map.Entry> set = map.entrySet(); for(Map.Entry entry:set){ System.out.println(entry.getKey()+"="+entry.getValue()); } /*333=zhaoliu 222=lisi 111=zhangsan 验证结果:无序不可重复! */ }}
🥅同时重写HashCode和equals
1、向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法!equals方法有可能调用,也有可能不调用。
拿put(k,v)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值,
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,equals不需要执行。
拿get(k)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值,
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,equals不需要执行。2、注意:如果一个类的equals方法重写了,那么hashCode()方法必须重写。
并且equals方法返回如果是true,hashCode()方法返回的值必须一样。
equals方法返回true表示两个对象相同,在同一个单向链表上比较。
那么对于同一个单向链表上的节点来说,他们的哈希值都是相同的。
所以hashCode()方法的返回值也应该相同。3、hashCode()方法和equals()方法可以直接使用IDEA工具生成,但是这两个方法需要同时生成。
4、终极结论:
放在HashMap集合key部分的,以及放在HashSet集合中的元素,需要同时重写hashCode方法和equals方法。5、对于哈希表数据结构来说:
如果o1和o2的hash值相同,一定是放到同一个单向链表上。
如果o1和o2的hash值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”。6、JDK8对HashMap集合的改进:如果哈希表单向链表中元素超过8个,单向链表这种数据结构会变成红黑树;当红黑树节点数量小于6时,会重新把红黑树变成单向链表;这种方式也是为了提高检索效率,二叉树的检索效率会再次缩小扫描范围,提高效率
⭐学生类
package com.bjpowernode.javase.map;import java.util.Objects;public class Student { private String name; // 构造方法 public Student() { } public Student(String name) { this.name = name; } // setter and getter public String getName() { return name; } public void setName(String name) { this.name = name; } // 同时生成equals方法和hashCode方法 public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return Objects.equals(name, student.name); } public int hashCode() { return Objects.hash(name); }}
⭐测试
package com.bjpowernode.javase.map;import java.util.HashSet;import java.util.Set;public class HashMapTest02 { public static void main(String[] args) { Student s1 = new Student("张三"); Student s2 = new Student("张三"); // 重写equlas方法之前 System.out.println(s1.equals(s2)); // false // 重写equals方法之后 System.out.println(s1.equals(s2)); // true System.out.println("s1的hashCode是:"+s1.hashCode()); // 1163157884(重写hashCode之后:774920) System.out.println("s2的hashCode是:"+s2.hashCode()); // 1956725890(重写hashCode之后:774920) System.out.println(s1.hashCode() == s2.hashCode()); // false // s1.equals(s2)结果已经是true了,表示s1和s2是一样的,相同的, // 那么往HashSet集合中放的话,按说只能放进去1个。(HashSet集合特点:无序不可重复) Set students = new HashSet(); students.add(s1); students.add(s2); System.out.println(students.size()); //2,但按理说应该是1,无序不可重复!重写hashCode方法 System.out.println(students.size()); // 1 重写hashCode以后结果就是1 }}
❤️HashMap的key可以为null
HashMap集合key部分允许null吗?
答:允许但是要注意:HashMap集合的key null值只能有一个;多了会被后面的覆盖
package com.bjpowernode.javase.map;import java.util.HashMap;import java.util.Map;public class HashMapTest03 { public static void main(String[] args) { Map map = new HashMap(); // HashMap集合允许key为null map.put(null,null); System.out.println(map.size()); // 1 // key重复的话value会被覆盖 map.put(null,100); System.out.println(map.size()); // 还是1 // 通过key获取value System.out.println(map.get(null)); // 100 }}
🥅HashMap和Hashtable的区别
(1)Hashtable的key可以为null吗?
Hashtable的key和value都是不能为null的。
HashMap集合的key和value都是可以为null的。(2)Hashtable方法都带有synchronized:线程安全的。线程安全有其它的方案,Hashtable对线程的处理导致效率较低,使用较少了。
Hashtable和HashMap一样,底层都是哈希表数据结构。
(3)HashMap集合的默认初始化容量是16,默认加载因子是0.75
扩容:扩容后的容量是原容量的2倍
Hashtable的初始化容量是11,默认加载因子是:0.75
扩容:原容量 * 2 + 1(4)关于容量,扩容小总结:
Collection集合:
1、ArrayList集合初始化容量是10;扩容到原容量的1.5倍!
2、Vector集合初始化容量是10;扩容到原容量的2倍!
3、HashSet集合初始化容量16,初始化容量建议是2的倍数;扩容:扩容之后是原容量2倍Map集合:
1、HashMap初始化容量16,默认加载因子0.75,扩容之后的容量是量的2倍。
2、 Hashtable集合初始化容量11,默认加载因子0.75,扩容之后的容量是原容量*2 + 1
package com.bjpowernode.javase.table;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class HashtableTest01 { public static void main(String[] args) { //1、 HashMap集合的key和value都是可以为null的 Map map1 = new HashMap(); map1.put(null,null); // 编译和运行都没问题 //2、 Hashtable的key和value都是不能为null的。 Map map2 = new Hashtable(); map2.put(null,"zhangsan"); // java.lang.NullPointerException map2.put(10,null); // java.lang.NullPointerException }}
🥅Properties类
目前只需要掌握Properties属性类对象的相关方法即可。
Properties是一个Map集合,继承Hashtable,Properties的key和value都是String类型。
Properties被称为属性类对象;Properties是线程安全的。
package com.bjpowernode.javase;import java.util.Properties;public class PropertiesTest01 { public static void main(String[] args) { // 创建一个Properties对象 Properties pro = new Properties(); // 存setProperyies pro.setProperty("username","root"); pro.setProperty("password","1234"); pro.setProperty("driver","com.mysql.jdbc.Driver"); // 通过key取value System.out.println(pro.getProperty("username")); //root System.out.println(pro.getProperty("password")); //1234 System.out.println(pro.getProperty("driver")); //com.mysql.jdbc.Driver }}
🥅TreeSet(TreeMap)集合
1、TreeSet集合底层实际上是一个TreeMap
2、TreeMap集合底层是一个二叉树。
3、放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。
4、TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序。
称为:可排序集合。5、TreeSet集合有什么用呢?我们拿一个很常见的需求来作为例子:
数据库中有很多数据:
userid name birth ------------------------------------- 1 zs 1980-11-11 2 ls 1980-10-11 3 ww 1981-11-11 4 zl 1979-11-11
编写程序从数据库当中取出数据,在页面展示用户信息的时候按照生日升序或者降序。
这个时候可以使用TreeSet集合,因为TreeSet集合放进去,拿出来就是有顺序的。
package com.bjpowernode.javase.map;import java.util.TreeSet;public class TreeSetTest01 { public static void main(String[] args) { // 演示TreeSet对String是可排序的 TreeSet ts = new TreeSet(); // 添加元素 ts.add("zhangsan"); ts.add("lisi"); ts.add("wangwu"); ts.add("wangliu"); // 遍历---升序排 for(String s :ts){ System.out.println(s); } TreeSet ts2 = new TreeSet(); ts2.add(300); ts2.add(600); ts2.add(100); ts2.add(10); ts2.add(200); for(Integer i :ts2){ System.out.println(i); } }}/*运行结果: lisi wangliu wangwu zhangsan 10 100 200 300 600*/
❤️TreeSet无法对自定义类型排序
(1)对自定义的类型来说,TreeSet可以排序吗?
以下程序中对于Person类型来说,无法排序。因为没有指定Person对象之间的比较规则。
谁大谁小并没有说明。(2)以下程序运行的时候出现了这个异常:
java.lang.ClassCastException:
class com.bjpowernode.javase.collection.Person
cannot be cast to class java.lang.Comparable
(3)出现这个异常的原因是:
Person类没有实现java.lang.Comparable接口。
package com.bjpowernode.javase.map;import java.util.TreeSet;public class TreeSetTest02 { public static void main(String[] args) { // 创建对象 Person p1 = new Person(32); Person p2 = new Person(20); Person p3 = new Person(30); // 创建集合 TreeSet ts = new TreeSet(); // 添加元素 ts.add(p1); ts.add(p2); ts.add(p3); // 遍历打印 for(Person p:ts){ System.out.println(p); } }}//自定义Person类class Person{ int age; public Person(int age){ this.age = age; } // 重写toString()方法 public String toString(){ return "Person[age="+age+"]"; }}
⭐实现Comparable接口,编写比较的逻辑
package com.bjpowernode.javase.map;import java.util.TreeSet;public class TreeSetTest03 { public static void main(String[] args) { Customer c1 = new Customer(32); Customer c2 = new Customer(20); Customer c3 = new Customer(30); Customer c4 = new Customer(25); // 创建TreeSet集合 TreeSet customers = new TreeSet(); // 添加元素 customers.add(c1); customers.add(c2); customers.add(c3); customers.add(c4); // 遍历 for (Customer c : customers){ System.out.println(c); } }}// 放在TreeSet集合中的元素需要实现java.lang.Comparable接口。// 并且实现compareTo方法。equals可以不写。class Customer implements Comparable{ int age; public Customer(int age){ this.age = age; } // 需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较! // k.compareTo(t.key) // 拿着参数k和集合中的每一个k进行比较,返回值可能是>0 age2) { return 1; } else { return -1; }*/ //return this.age - c.age; //升序 return c.age - this.age; //降序 } public String toString(){ return "Customer[age="+age+"]"; }}
⭐比较规则怎么写
我们不妨编写一个,先按照年龄升序,如果年龄一样的再按照姓名升序。
compareTo方法的返回值很重要:
返回0表示相同,value会覆盖。
返回>0,会继续在右子树上找。
返回<0,会继续在左子树上找。
package com.bjpowernode.javase.map;import java.util.TreeSet;//先按照年龄升序,如果年龄一样的再按照姓名升序。public class TreeSetTest04 { public static void main(String[] args) { Vip v1 = new Vip("zhangsan",18); Vip v2 = new Vip("zhangzl",18); Vip v3 = new Vip("lisi",32); Vip v4 = new Vip("wangwu",20); Vip v5 = new Vip("zhaoliu",22); // 创建集合 TreeSet ts = new TreeSet(); // 增加元素 ts.add(v1); ts.add(v2); ts.add(v3); ts.add(v4); ts.add(v5); // 遍历打印 for(Vip v :ts){ System.out.println(v); } }}class Vip implements Comparable{ String name; int age; // 构造方法 public Vip(String name, int age) { this.name = name; this.age = age; } // 重写toString方法 public String toString() { return "Vip{" + "name='" + name + '\'' + ", age=" + age + '}'; //Vip{name='zhangsan', age=18} } // 重写Comparable接口中中的方法 public int compareTo(Vip o) { if(this.age != o.age){ return this.age - o.age; }else{ // 年龄相同,按照名字排序 // 名字是String类型,可以直接比,调用compareTo来比较 return this.name.compareTo(o.name); } }}/*运行结果: Vip{name='zhangsan', age=18} Vip{name='zhangzl', age=18} Vip{name='wangwu', age=20} Vip{name='zhaoliu', age=22} Vip{name='lisi', age=32}*/
🥅自平衡二叉树数据结构
1、TreeSet/TreeMap是自平衡二叉树遵循左小右大原则存放。
2、遍历二叉树的时候有三种方式:
前序遍历∶根左右
中序遍历∶左根右后序遍历∶左右根
注意:前中后说的是“根”的位置,根在前面是前序、根在中间是中序、根在后面是后序3、TreeSet/TreeMap集合采用的是:中序遍历方式,即Iterator迭代器采用的是中序遍历方式
4、我们就拿一组数据,写出它的二叉树结构,来体验一下中序遍历的方式,例如:100 200 50 60 80 120 140 130 135 180 666 40 55
5、中序遍历方式取出:40 50 55 60 80 100 120 130 135 140 180 200 666,按照中序遍历的方式取出来的刚好是有序的
🥅实现比较器接口
TreeSet集合中元素可排序的第二种方式:使用比较器的方式:
这种实现方式是根据原码来定义的,
如果我们使用无参的:调用的是Comparable接口里的compareTo方法如果我们使用有参的:调用的是Comparator里的compare方法
Comparable是java.lang包下的。Comparator是java.util包下的。)
最终的结论:
放到TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:
第一种:放在集合中的元素实现java.lang.Comparable接口。
第二种:在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。
Comparable和Comparator怎么选择呢?
当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实现Comparable接口。
如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
Comparator接口的设计符合OCP原则。
package com.bjpowernode.javase.map;import java.util.Comparator;import java.util.TreeSet;public class TreeSetTest05 { public static void main(String[] args) { Animals animals = new Animals(15); // 创建TreeSet集合的时候,需要使用这个比较器 // TreeSet animal = new TreeSet(); //原来这种方式就不行,没有使用比较器 // TreeSet animal = new TreeSet(new AnimalComparator()); //new一个比较器对象传过去 // 这里也可以不写Comparator接口的实现,使用匿名内部类 TreeSet animal = new TreeSet(new Comparator() { public int compare(Animals o1, Animals o2) { return o1.age - o2.age; } }); animal.add(new Animals(100)); animal.add(new Animals(80)); animal.add(new Animals(81)); // 循遍历 for(Animals a:animal){ System.out.println(a); } }}class Animals{ int age; // 构造方法 public Animals(int age) { this.age = age; } // 重写toString方法 public String toString() { return "Animals{" + "age=" + age + '}'; // Animals{age=15} }}/*// 单独在这里编写一个比较器// 比较器实现java.util.Comparator接口。class AnimalComparator implements Comparator { public int compare(Animals o1, Animals o2) { // 指定比较规则;按照年龄排序 return o1.age - o2.age; }}*/
🥅集合工具类Collections
java.util.Collection 集合接口
java.util.Collections 集合工具类,方便集合的操作。
package com.bjpowernode.javase;import java.util.*;public class CollectionsTest { public static void main(String[] args) { // 1、 ArrayList集合不线程安全的 List list = new ArrayList(); // 通过Collections集合里的方法变成线程安全的 Collections.synchronizedList(list); //排序 list.add("abf"); list.add("abx"); list.add("abc"); list.add("abe"); Collections.sort(list); //排序 // 打印 for(String s:list){ System.out.println(s); // abc abe abf abx } // 2、如果排序自己写的类,需要自己实现compareTo接口 List wuGui2s = new ArrayList(); wuGui2s.add(new WuGui2(1000)); wuGui2s.add(new WuGui2(800)); // 注意:对List集合中元素排序,需要保证List集合中的元素实现了:Comparable接口。 Collections.sort(wuGui2s); for(WuGui2 w : wuGui2s){ System.out.println(w); } // 3、对Set集合怎么排序呢? Set set = new HashSet(); set.add("king"); set.add("kingsoft"); set.add("king2"); set.add("king1"); //Collections.sort(); //里面只能是List集合 // 所以需要把Set集合转换成List集合 List mylist = new ArrayList(set);// 把set集合转过来 Collections.sort(mylist); //这样就能排序了 for(String s:mylist){ System.out.println(s); // king king1 king2 kingsoft } // 这种方式也可以排序。 //Collections.sort(list集合, 比较器对象); }}class WuGui2 implements Comparable{ int age; public WuGui2(int age){ this.age = age; } public int compareTo(WuGui2 o) { return this.age - o.age; } public String toString() { return "WuGui2{" + "age=" + age + '}'; }}