容器也称作“集合”。在Java中我们可以使用“容器”来容纳和管理数据。容器很好的解决了数组不灵活,不可以随时扩容的问题。
容器的相关类都定义了泛型,在开发工作中,使用容器类时都要使用泛型。这样,在容器中存储和读取数据时避免了大量的类型判断,更加便捷。
泛型是JDK1.5中的一个新特性,其本质是“参数化类型”,亦即所操作的数据类型被指定为一个类型参数(Type Parameter),这种参数类型(亦即,泛型类型变量或泛型符号)可以用在类、接口、方法的创建中,分别称为泛型类、泛型接口、泛型方法。
参数类型(亦即,泛型类型变量或泛型符号)由尖括号界定,放在类或接口名的后面,如“public class className<T>{}”;其中"T"称为泛型类型变量(亦即,泛型符号),意味着一个变量将被一个类型替代,替代类型变量的值将被当作参数或返回类型,同时参数类型(亦即,泛型类型变量或泛型符号)只是一个符号(即,占位符)而已,不存在任何意义,我们一般习惯使用一个大写的字母(如“T”或"E"或"K"或"V")。其示例如以下代码所示。
public class GenericsClass<V> {}//泛型类 public interface GenericsInterface<T> {}//泛型接口 public class GenericsClass<T> implements GenericsInterface<T> {}//实现泛型接口的泛型类
是否拥有泛型方法,与其所在的类是否泛型无关。要定义泛型方法,只需将泛型参数列表置于返回值前。使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了与普通方法定义不同,其方法调用与普通方法一样。
2.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.Date; public class GenericsMethod { public static void main(String[] args) { new GenericsMethod().callGenericsMethod(); } public void callGenericsMethod() { genericsMethod(new Date()); } /** * 泛型方法 * @param t * @param <T> * @return */ public static <T> T genericsMethod(T t) { System.out.println("genericsMethod:" + t); return null; } }
2.2、运行结果(Run Result)
其运行结果,如以下信息所示。
genericsMethod:Sun Jul 18 16:57:24 CST 2021
3.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; public class ArrayListClass { public static void main(String[] args) { /** *创建Collection容器(集合) */ Collection<String> collection=new ArrayList<>(); //清空列表元素 collection.clear(); //添加指定元素至列表末尾 System.out.println(collection.add("1")); System.out.println(collection.add("2")); System.out.println(collection.add("3")); //删除列表指定元素 System.out.println(collection.remove("3")); System.out.println(collection.remove("3")); //获取列表元素的总数量 System.out.println(collection.size()); //判断列表是否为空 System.out.println(collection.isEmpty()); //判断是否包含某个元素 System.out.println(collection.contains("1")); //将列表元素转换为数组 //System.out.println(collection); System.out.println(collection.toArray()); //使用Arrays类toString方法数组元素 System.out.println(Arrays.toString(collection.toArray())); /** *创建List容器(集合) */ List<String> list=new ArrayList<>(); //清空列表元素 list.clear(); //添加指定元素至列表末尾 System.out.println(list.add("a")); System.out.println(list.add("b")); System.out.println(list.add("c")); System.out.println(list.add("d")); //删除列表指定元素 System.out.println(list.remove("c")); System.out.println(list.remove("c")); //获取列表元素的总数量 System.out.println(list.size()); //判断列表是否为空 System.out.println(list.isEmpty()); //判断是否包含某个元素 System.out.println(list.contains("a")); //将列表元素转换为数组 //System.out.println(list); System.out.println(list.toArray()); //将列表中指定索引位置的数据更改为指定数据 list.set(1,"d"); //将列表中指定索引位置插入指定数据,原来指定索引位置及其之后数据整体往后移一位 list.add(1,"e"); //将列表中指定索引位置的数据删除,原来指定索引位置及其之后数据整体往前移一位 list.remove(1); //获取列表中指定索引位置的数据 System.out.println(list.get(1)); //获取列表中指定元素的第一次出现的索引(从前往后顺序查找),若未找到则返回-1 System.out.println(list.indexOf("d")); //获取列表中指定元素的最后一次出现的索引(从后往前顺序查找),若未找到则返回-1 System.out.println(list.lastIndexOf("d")); //截取列表中的指定开始位置到结束位置之间(不含结束位置)的数据 System.out.println(list.subList(1,list.size())); //使用Arrays类toString方法数组元素 System.out.println(Arrays.toString(list.toArray())); //使用Arrays类asList方法初始化列表数据:1、数组的修改会影响原数组,2、允许null值,且处理null值不会有异常 List<String> list1=Arrays.asList("a","b","c"); System.out.println(Arrays.toString(list1.toArray())); //使用List接口of方法(JDK1.9新特性)初始化列表数据:1、数组的修改不会影响原数组,2、不允许null值,且处理null值会有NullPointerException(空指针)异常 List<String> list2=List.of("a","b","c"); System.out.println(Arrays.toString(list2.toArray())); } }
3.2、运行结果(Run Result)
其运行结果,如以下信息所示。
true true true true false 2 false true [Ljava.lang.Object;@119d7047 [1, 2] true true true true true false 3 false true [Ljava.lang.Object;@776ec8df d 1 2 [d, d] [a, d, d] [a, b, c] [a, b, c]
4.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class ListContainerTraversal { public static void main(String[] args) { //使用Arrays工具类asList方法静态初始化List容器(集合) System.out.println("使用Arrays工具类asList方法静态初始化List容器(集合):"); List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6"); //使用普通For循环遍历List容器(方式一) System.out.println("使用普通For循环遍历List容器(方式1)"); //for (int i = 0; i < list.toArray().length; i++) {} for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + "\t"); } System.out.println(); //使用增强For循环遍历List容器(方式二) System.out.println("使用增强For循环遍历List容器(方式2)"); for (String s : list) { System.out.print(s + "\t"); } System.out.println(); //使用迭代器循环遍历List容器(方式三) System.out.println("使用迭代器循环遍历List容器(方式3)"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + "\t"); } System.out.println(); //使用List容器of方法静态初始化List容器(集合) System.out.println("使用List容器of方法静态初始化List容器(集合):"); List<String> list1 = List.of("未来", "美好", "中国", "繁荣", "世界", "和平");//JDK1.9新特性 //使用普通For循环遍历List容器(方式一) System.out.println("使用普通For循环遍历List容器(方式一)"); //for (int i = 0; i < list1.toArray().length; i++) {} for (int i = 0; i < list1.size(); i++) { System.out.print(list1.get(i) + "\t"); } System.out.println(); //使用增强For循环遍历List容器(方式二) System.out.println("使用增强For循环遍历List容器(方式二)"); for (String s1 : list1) { System.out.print(s1 + "\t"); } System.out.println(); //使用迭代器循环遍历List容器(方式三) System.out.println("使用迭代器循环遍历List容器(方式三)"); Iterator<String> iterator1 = list1.iterator(); while (iterator1.hasNext()) { System.out.print(iterator1.next() + "\t"); } System.out.println(); Iterator<String> iterator2 = list1.iterator(); for (; iterator2.hasNext(); ) { System.out.print(iterator2.next() + "\t"); } System.out.println(); Iterator<String> iterator3 = list1.iterator(); for (Iterator<String> it = iterator3; it.hasNext(); ) { System.out.print(it.next() + "\t"); } System.out.println(); } }
4.2、运行结果(Run Result)
其运行结果,如以下信息所示。
使用Arrays工具类asList方法静态初始化List容器(集合): 使用普通For循环遍历List容器(方式1) 1 2 3 4 5 6 使用增强For循环遍历List容器(方式2) 1 2 3 4 5 6 使用迭代器循环遍历List容器(方式3) 1 2 3 4 5 6 使用List容器of方法静态初始化List容器(集合): 使用普通For循环遍历List容器(方式一) 未来 美好 中国 繁荣 世界 和平 使用增强For循环遍历List容器(方式二) 未来 美好 中国 繁荣 世界 和平 使用迭代器循环遍历List容器(方式三) 未来 美好 中国 繁荣 世界 和平 未来 美好 中国 繁荣 世界 和平 未来 美好 中国 繁荣 世界 和平
5.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class MapContainerCommonMethod { public static void main(String[] args) { //创建Map容器 Map<String, Integer> map = new HashMap<>(); //添加Map容器数据 map.put("001",1); map.put("002",2); map.put("003",3); //Map容器数据的总数量 System.out.println(map.size()); //Map容器是否为空 System.out.println(map.isEmpty()); //Map容器是否包含指定Key System.out.println(map.containsKey("001")); //Map容器是否包含指定Value System.out.println(map.containsValue(1)); //获取Map容器指定Key对应Value System.out.println(map.get("001")); //获取Map容器指定Key对应Value,若没有则给指定默认Value System.out.println(map.getOrDefault("003",0)); //移除Map容器指定Key数据 System.out.println(map.remove("002")); //移除Map容器指定Key与指定Value数据 System.out.println(map.remove("003",1)); //替换Map容器指定Key数据 map.replace("003",1); System.out.println(map.get("003")); //替换Map容器指定Key与指定Value数据 map.replace("003",1,2); System.out.println(map.get("003")); //将Map容器数据转换为数组 System.out.println(map.values().toArray()); //输出Map容器数据 System.out.println(map); System.out.println(map.values()); System.out.println(Arrays.toString(map.values().toArray())); //清空Map容器 map.clear(); //静态初始化Map容器 Map<String, Integer> map1=Map.of("IDEA",1,"Eclipse",2,"MyEclipse",3); System.out.println(map1); System.out.println(map1.values()); System.out.println(Arrays.toString(map1.values().toArray())); } }
5.2、运行结果(Run Result)
其运行结果,如以下信息所示。
3 false true true 1 3 2 false 1 2 [Ljava.lang.Object;@119d7047 {001=1, 003=2} [1, 2] [1, 2] {MyEclipse=3, IDEA=1, Eclipse=2} [3, 1, 2] [3, 1, 2]
6.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Map容器中Key是不允许重复的,若重复只能被存放一次,且后面的数据会覆盖前面的数据(即,只保留最新一次数据) * 由于Map容器中Key都是引用类型数据,所以使用equals方法来比较是否相等 */ public class MapContainerKey { public static void main(String[] args) { //创建Map容器对象 Map<String, Integer> map = new HashMap<>(); //添加Map容器数据 map.put("1", 1); map.put("2", 2); map.put("3", 3); map.put("3", 4); //Map容器数据的总数量 System.out.println(map.size()); //获取Map容器指定Key对应Value System.out.println(map.get("3")); //创建Map容器对象 Map<Employee,Integer> map1=new HashMap<>(); //添加Map容器数据 map1.put(new Employee(1,"昨天"),1); map1.put(new Employee(2,"今天"),2); map1.put(new Employee(3,"未来"),1); map1.put(new Employee(3,"明天"),3); //Map容器数据的总数量 System.out.println(map1.size()); //输出Map容器数据 System.out.println(map1); System.out.println(map1.values()); System.out.println(Arrays.toString(map1.values().toArray())); } } class Employee implements Serializable { private static final long serialVersionUID = -5289179772697078118L; private int id; private String name; //无参构造器 public Employee() { } //有参构造器 public Employee(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } //重写toString方法 @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + '}'; } //重写equals方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; return id == employee.id; } //重写hashCode方法 @Override public int hashCode() { return Objects.hash(id); } }
6.2、运行结果(Run Result)
其运行结果,如以下信息所示。
3 4 3 {Employee{id=1, name='昨天'}=1, Employee{id=2, name='今天'}=2, Employee{id=3, name='未来'}=3} [1, 2, 3] [1, 2, 3]
7.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.Iterator; import java.util.Map; /** * Map容器中存放的数据是无序的 */ public class MapContainerTraversal { public static void main(String[] args) { //使用Map容器of方法静态初始化Map容器(集合) System.out.println("使用Map容器of方法静态初始化Map容器(集合):"); Map<Integer, String> map = Map.of(1, "1", 2, "2", 3, "3"); //使用Map容器keySet方法获取Key的增强For循环遍历Map容器(方式1) System.out.println("使用Map容器keySet方法获取Key的增强For循环遍历Map容器(方式1)"); for (Integer integer : map.keySet()) { System.out.println("key=" + integer + ",value=" + map.get(integer)); } //使用Map容器entrySet方法获取Key与value的增强For循环遍历Map容器(方式2) System.out.println("使用Map容器keySet方法获取Key与value的增强For循环遍历Map容器(方式2)"); for (Map.Entry<Integer, String> integerStringEntry : map.entrySet()) { System.out.println("key=" + integerStringEntry.getKey() + ",value=" + integerStringEntry.getValue()); } //使用Map容器keySet方法获取Key的迭代器遍历Map容器(方式3) System.out.println("使用Map容器keySet方法获取Key的迭代器遍历Map容器(方式3)"); Iterator<Integer> iterator1 = map.keySet().iterator(); while (iterator1.hasNext()) { Integer key = iterator1.next(); System.out.println("key=" + key + ",value=" + map.get(key)); } Iterator<Integer> iterator2 = map.keySet().iterator(); for (; iterator2.hasNext(); ) { Integer key = iterator2.next(); System.out.println("key=" + key + ",value=" + map.get(key)); } Iterator<Integer> iterator3 = map.keySet().iterator(); for (Iterator<Integer> it = iterator3; it.hasNext(); ) { Integer key = it.next(); System.out.println("key=" + key + ",value=" + map.get(key)); } } }
7.2、运行结果(Run Result)
其运行结果,如以下信息所示。
使用Map容器of方法静态初始化Map容器(集合): 使用Map容器keySet方法获取Key的增强For循环遍历Map容器(方式1) key=3,value=3 key=2,value=2 key=1,value=1 使用Map容器keySet方法获取Key与value的增强For循环遍历Map容器(方式2) key=3,value=3 key=2,value=2 key=1,value=1 使用Map容器keySet方法获取Key的迭代器遍历Map容器(方式3) key=3,value=3 key=2,value=2 key=1,value=1 key=3,value=3 key=2,value=2 key=1,value=1 key=3,value=3 key=2,value=2 key=1,value=1
8.2、数组内存结构优缺点(Array Memory Strcture Advantages And Disadvantages)
优点
数据类型相同、内存空间连续、可随机访问数据。
缺点
插入或删除数据时,会导致数据的整体迁移。
总结:访问数组数据速度快,插入或删除数组数据慢。
9.2、链表内存结构优缺点(Linked List Memory Strcture Advantages And Disadvantages)
优点
可以更好的进行插入或删除数据。
缺点
查找数据很慢,不支持随机访问数据。
总结:访问链表数据速度慢,插入或删除链表数据快。
问题一(内容):假如Map的Key不是数值型,如何进行取余计算索引下标? 问题一(解决方案):调用Key的hashCode方法,将其转换为哈希码值(即,将任意类型转为数值型)进行取余计算索引下标。 其中,使用数学原理:“将一个未知的问题转换为一个已知的问题,问题就可以解决了”。 且Map的Key都是引用数据类型,根基类是Object,都有hashCode方法。 问题二(内容):新增数据时,Map如何扩容? 问题二(解决方案):当新增数据的数量达到Map门槛时,Map会自动进行扩容,且默认初始容量(即,默认初始数组长度)为“(1<<4)=16”,默认因子为“0.75f”,默认门槛为“16*0.75=12”,最大容量(即,最大数组长度)为“(1<<30)=1073741824”。 哈希码值的上限是“(2^31-1)=((1<<31)-1)=2147483647”,当超过哈希码值的上限时,不管有多大,最终都会存到数组中,理论上只要内存足够大,Map可以存放无限多个数据。 问题三(内容):虽然两个Key的哈希码值不同,但是其取余后索引下标相同,此时同一个索引下标位置如何存放这些数据? 问题三(解决方案一):可以设置一个因子(Factor),然后“容量(数组长度)*因子”就是本次扩容门槛。基于HashMap类的Map容器不能等用完才扩容,否则容易重复,只要达到Map门槛时就会扩容(用空间换时间<缓存>);而基于ArrayList类的List容器是等用完后才开始扩容。 问题三(解决方案二情形1):在JDK8时,先判断两个Key的hashCode是否相同,再判断两个Key的内容是否相同(equals),若相同则直接替换,若不相同,创建新对象,让新对象的next指向索引位置的旧对象,然后在索引位置存放新对象。 问题三(解决方案二情形2):在JDK11时,先判断两个Key的hashCode是否相同,再判断两个Key的内容是否相同(equals),若相同则直接替换,若不相同,创建新对象,接着查找索引位置的最后一个旧对象,让最后一个旧对象的next指向新对象。
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class DuringListContainerTraversalAddAndDeleteData { public static void main(String[] args) { List<String> list1 = new ArrayList<>(); list1.add("0"); list1.add("1"); list1.add("1"); list1.add("2"); list1.add("1"); list1.add("3"); // /** // *List容器遍历时添加数据,由于List容器size方法会随着数据添加而一直增加,从而陷入死循环,因此不允许在遍历时添加数据 // */ // for (int i = 0; i < list1.size(); i++) { // System.out.println(i+"-"+list1.size()); // list1.add(String.valueOf(i+1)); // } // /** // *List容器使用For循环遍历时删除数据(错误方式) // *由于删除数组数据后,删除数据索引后的所有数据整体前移,且删除数据索引的新数据不会再被判断,而是从下一个索引继续判断,因此可能会遗漏重复的指定删除数据 // */ // for (int i = 0; i < list1.size(); i++) { // System.out.println(i+"-"+list1.size()+"-"+ list1.get(i)); // if("1".equals(list1.get(i))){ // list1.remove(i); // } // } // System.out.println(Arrays.toString(list1.toArray())); // /** // *List容器使用For循环遍历时删除数据(正确方式) // *由于数组从后往前遍历,无论删除数据是否成功(即,无论数据是否前移),数组中的每一个数据都不会漏掉 // */ // for (int i = list1.size() - 1; i >= 0; i--) { // System.out.println(i + "-" + list1.size() + "-" + list1.get(i)); // if ("1".equals(list1.get(i))) { // list1.remove(i); // } // } // System.out.println(Arrays.toString(list1.toArray())); // /** // *List容器使用增强For循环遍历时删除数据 // *由于删除数据后会改变遍历数据的结构,所以会抛出“并发修改异常(ConcurrentModificationException)”,因此不允许在使用增强For循环遍历时删除数据 // *若实在想使用增强For循环遍历时删除数据,只能在删除一个元素后立刻退出循环,但强烈不建议使用此方法 // */ // for (String s : list1) { // System.out.println(s+"-前"); // if("1".equals(s)){ // list1.remove(s); // } // System.out.println(s+"-后"); // } // /** // *List容器使用迭代器循环遍历时删除数据(方式一):使用while循环 // */ // Iterator<String> iterator1=list1.iterator(); // while(iterator1.hasNext()){ // String strNext=iterator1.next(); // System.out.println(strNext+"-前"); // if("1".equals(strNext)){ // //list1.remove(strNext);//错误的删除方式 // iterator1.remove();//正确的删除方式 // } // System.out.println(strNext+"-后"); // } // System.out.println(Arrays.toString(list1.toArray())); /** *List容器使用迭代器循环遍历时删除数据(方式二):使用快捷键itco,推荐使用 */ for (Iterator<String> iterator = list1.iterator(); iterator.hasNext(); ) { String next = iterator.next(); System.out.println(next+"-前"); if("1".equals(next)){ //list1.remove(next);//错误的删除方式 iterator.remove();//正确的删除方式 } System.out.println(next+"-后"); } System.out.println(Arrays.toString(list1.toArray())); } }
其操作步骤,如下图所示。
14.1、创建resources目录。
14.2、将resources目录设置为Resources Root类型。
14.3、创建resources目录的配置文件。
14.4、设置resources目录中配置文件的参数。
15.1、示例代码(Sample Code)
15.1.1、不使用静态代码块读取配置文件
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.IOException; import java.util.Properties; /** * 使用Properties工具类将配置文件参数读取到内存(方法1):不使用静态代码块读取配置文件 */ public class UsePropertiesClassReadConfigureFile1 { public static void main(String[] args) throws IOException { //创建Properties工具类对象 Properties properties = new Properties(); //使用Properties工具类load方法加载资源配置文件 properties.load(UsePropertiesClassReadConfigureFile1.class.getClassLoader().getResourceAsStream("set.properties")); //获取配置文件的参数数据 System.out.println("不使用静态代码块读取配置文件"); System.out.println("UID=" + properties.getProperty("UID")); System.out.println("PWD=" + properties.getProperty("PWD")); } }
其运行结果,如以下信息所示。
不使用静态代码块读取配置文件 UID=resources root PWD=properties
15.1.2、使用静态代码块读取配置文件
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.IOException; import java.util.Properties; /** * 使用Properties工具类将配置文件参数读取到内存(方法2):使用静态代码块读取配置文件 */ public class UsePropertiesClassReadConfigureFile2 { public static final String MYUID; public static final String MYPWD; /** *使用静态代码块读取配置文件 */ static { //创建Properties工具类对象 Properties properties = new Properties(); //使用Properties工具类load方法加载资源配置文件 try { properties.load(UsePropertiesClassReadConfigureFile1.class.getClassLoader().getResourceAsStream("set.properties")); } catch (IOException e) { e.printStackTrace(); } //获取配置文件的参数数据 MYUID=properties.getProperty("UID"); MYPWD=properties.getProperty("PWD"); } public static void main(String[] args) { System.out.println("使用静态代码块读取配置文件"); System.out.println("UID=" + MYUID); System.out.println("PWD=" + MYPWD); } }
其运行结果,如以下信息所示。
使用静态代码块读取配置文件 UID=resources root PWD=properties
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; /** * 使用Properties工具类将配置文件参数写出到磁盘 */ public class UsePropertiesClassWriteConfigureFile { public static void main(String[] args) throws IOException { //创建Properties工具类对象 Properties propertiesWrite = new Properties(); //添加数据 propertiesWrite.put("ID", "001"); propertiesWrite.put("UID", "ResourcesRoot"); propertiesWrite.put("PWD", "Properties"); propertiesWrite.put("Test", "Test"); //配置文件名称 String myConfigureFileName = "test.properties"; //写入配置文件的参数数据 OutputStream outputStream = new FileOutputStream(new File("").getCanonicalPath() + File.separator + "javase" +File.separator + "resources" + File.separator + myConfigureFileName); propertiesWrite.store(outputStream, "使用Properties工具类将配置文件参数写出到磁盘"); } }
17.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.Serializable; import java.util.*; public class ImplementComparableInterface { public static void main(String[] args) { //创建String类的List List<String> list1=new ArrayList<>(); list1.add("1"); list1.add("3"); list1.add("2"); list1.add("4"); //随机排列List Collections.shuffle(list1); System.out.println(Arrays.toString(list1.toArray())); //反转List Collections.reverse(list1); System.out.println(Arrays.toString(list1.toArray())); //排序List Collections.sort(list1); System.out.println(Arrays.toString(list1.toArray())); //创建Student类的List List<Student> list2=new ArrayList<>(); list2.add(new Student(1,"ad",99,11)); list2.add(new Student(3,"ae",66,15)); list2.add(new Student(2,"as",88,17)); list2.add(new Student(5,"ae",77,13)); list2.add(new Student(4,"af",55,5)); Collections.sort(list2); System.out.println(Arrays.toString(list2.toArray())); } } /** *通过实现Comparable接口来比较排序对象 */ class Student implements Serializable,Comparable<Student> { private static final long serialVersionUID = -482298316433918710L; private int id; private String name; private double score; private transient int age; public Student() { } public Student(int id, String name, double score, int age) { this.id = id; this.name = name; this.score = score; this.age = age; } public static long getSerialVersionUID() { return serialVersionUID; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return id == student.id && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(id, name); } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", score=" + score + ", age=" + age + '}'; } //重写Comparable接口的compareTo方法 @Override public int compareTo(Student o) { // //开始比较要排序的属性,按照id进行升序/降序排序 // //return this.id-o.getId();//id升序 // return this.getId()-o.getId();//id升序 // //return (this.id-o.getId())*-1;//id降序 // return (this.getId()-o.getId())*-1;//id降序 //开始比较要排序的属性,先按照name升序/降序排序,若名字相同则按照id进行升序/降序排序 int result=this.getName().compareTo(o.getName()); if(result==0){//name相同 //继续比较id //result=this.id-o.getId(); result=this.getId()-o.getId(); //return result;//id升序 return result*-1;//id降序 } //return result;//name升序 return result*-1;//name降序 } }
17.2、运行结果(Run Result)
其运行结果,如以下信息所示。
[3, 2, 1, 4] [4, 1, 2, 3] [1, 2, 3, 4] [Student{id=2, name='as', score=88.0, age=17}, Student{id=4, name='af', score=55.0, age=5}, Student{id=5, name='ae', score=77.0, age=13}, Student{id=3, name='ae', score=66.0, age=15}, Student{id=1, name='ad', score=99.0, age=11}]
18.1、示例代码(Sample Code)
其示例,如以下代码所示。
package com.xueshanxuehai.genericsandcontainers; import java.io.Serializable; import java.util.*; public class ImplementComparatorInterface { public static void main(String[] args) { System.out.println(new Teacher(4,"af",800,19)); //创建Teacher类的List List<Teacher> list=new ArrayList<>(); list.add(new Teacher(1,"ad",3000,55)); list.add(new Teacher(3,"ae",1000,22)); list.add(new Teacher(2,"as",2000,44)); list.add(new Teacher(5,"ae",1100,33)); list.add(new Teacher(4,"af",800,19)); System.out.println("通过实现Comparator接口来比较排序对象"); System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); //人力部门按照id(编号)升序排序 System.out.println("人力部门按照id(编号)升序排序"); Collections.sort(list,new HumanResourcesComparatorAsc()); System.out.println(Arrays.toString(list.toArray())); //人力部门按照id(编号)降序排序 System.out.println("人力部门按照id(编号)降序排序"); Collections.sort(list,new HumanResourcesComparatorDesc()); System.out.println(Arrays.toString(list.toArray())); //财务部门按照sal(薪资)升序排序 System.out.println("财务部门按照sal(薪资)升序排序"); Collections.sort(list,new FinanceComparatorAsc()); System.out.println(Arrays.toString(list.toArray())); //财务部门按照sal(薪资)降序排序 System.out.println("财务部门按照sal(薪资)降序排序"); Collections.sort(list,new FinanceComparatorDesc()); System.out.println(Arrays.toString(list.toArray())); //考勤部门按照name(名称)升序排序 System.out.println("考勤部门按照name(名称)升序排序"); Collections.sort(list,new AttendanceComparatorAsc()); System.out.println(Arrays.toString(list.toArray())); //考勤部门按照name(名称)降序排序 System.out.println("考勤部门按照name(名称)降序排序"); Collections.sort(list,new AttendanceComparatorDesc()); System.out.println(Arrays.toString(list.toArray())); //管理部门按照age(年龄)升序排序 System.out.println("管理部门按照age(年龄)升序排序"); Collections.sort(list,new ManageComparatorAsc()); System.out.println(Arrays.toString(list.toArray())); //管理部门按照age(年龄)降序排序 System.out.println("管理部门按照age(年龄)降序排序"); Collections.sort(list,new ManageComparatorDesc()); System.out.println(Arrays.toString(list.toArray())); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); System.out.println("通过匿名内部类来比较排序对象"); System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); //考勤部门按照name(名称)升序排序 System.out.println("考勤部门按照name(名称)升序排序"); Collections.sort(list, new Comparator<Teacher>() { @Override public int compare(Teacher o1, Teacher o2) { return o1.getName().compareTo(o2.getName()); } }); System.out.println(Arrays.toString(list.toArray())); //考勤部门按照name(名称)降序排序 System.out.println("考勤部门按照name(名称)降序排序"); Collections.sort(list, new Comparator<Teacher>() { @Override public int compare(Teacher o1, Teacher o2) { return (o1.getName().compareTo(o2.getName()))*-1; } }); System.out.println(Arrays.toString(list.toArray())); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); System.out.println("通过Lambda表达式来比较排序对象"); System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); //考勤部门按照name(名称)降序排序 System.out.println("考勤部门按照name(名称)降序排序"); Collections.sort(list,(t1,t2)->{ return 1;//原样排序列表(即,列表排序不变) }); System.out.println(Arrays.toString(list.toArray())); //考勤部门按照name(名称)升序排序 System.out.println("考勤部门按照name(名称)升序排序"); Collections.sort(list,(t1,t2)->{ return -1;//反转排序列表(即,逆序排序列表) }); System.out.println(Arrays.toString(list.toArray())); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); } } /** *通过实现Comparator接口来比较排序对象 *人力部门按照id(编号)升序排序 */ class HumanResourcesComparatorAsc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return o1.getId()-o2.getId(); } } /** *通过实现Comparator接口来比较排序对象 *人力部门按照id(编号)降序排序 */ class HumanResourcesComparatorDesc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return (o1.getId()-o2.getId())*-1; } } /** *通过实现Comparator接口来比较排序对象 *财务部门按照sal(薪资)升序排序 */ class FinanceComparatorAsc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return (int) (o1.getSal()-o2.getSal()); } } /** *通过实现Comparator接口来比较排序对象 *财务部门按照sal(薪资)降序排序 */ class FinanceComparatorDesc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return ((int) (o1.getSal()-o2.getSal()))*-1; } } /** *通过实现Comparator接口来比较排序对象 *考勤部门按照name(名称)升序排序 */ class AttendanceComparatorAsc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return o1.getName().compareTo(o2.getName()); } } /** *通过实现Comparator接口来比较排序对象 *考勤部门按照name(名称)降序排序 */ class AttendanceComparatorDesc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return (o1.getName().compareTo(o2.getName()))*-1; } } /** *通过实现Comparator接口来比较排序对象 *管理部门按照age(年龄)升序排序 */ class ManageComparatorAsc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return o1.getAge()-o2.getAge(); } } /** *通过实现Comparator接口来比较排序对象 *管理部门按照age(年龄)降序排序 */ class ManageComparatorDesc implements Comparator<Teacher>{ //重写Comparator接口的compare方法 @Override public int compare(Teacher o1, Teacher o2) { return (o1.getAge()-o2.getAge())*-1; } } class Teacher implements Serializable { private static final long serialVersionUID = -5389180768711652314L; private int id; private String name; private double sal; private transient int age; public Teacher() { } public Teacher(int id, String name, double sal, int age) { this.id = id; this.name = name; this.sal = sal; this.age = age; } public static long getSerialVersionUID() { return serialVersionUID; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Teacher teacher = (Teacher) o; return id == teacher.id && Objects.equals(name, teacher.name); } @Override public int hashCode() { return Objects.hash(id, name); } @Override public String toString() { return "Teacher{" + "id=" + id + ", name='" + name + '\'' + ", sal=" + sal + ", age=" + age + '}'; } }
18.2、运行结果(Run Result)
其运行结果,如以下信息所示。
通过实现Comparator接口来比较排序对象 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 人力部门按照id(编号)升序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=5, name='ae', sal=1100.0, age=33}] 人力部门按照id(编号)降序排序 [Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=1, name='ad', sal=3000.0, age=55}] 财务部门按照sal(薪资)升序排序 [Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=1, name='ad', sal=3000.0, age=55}] 财务部门按照sal(薪资)降序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=4, name='af', sal=800.0, age=19}] 考勤部门按照name(名称)升序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=2, name='as', sal=2000.0, age=44}] 考勤部门按照name(名称)降序排序 [Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=1, name='ad', sal=3000.0, age=55}] 管理部门按照age(年龄)升序排序 [Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=1, name='ad', sal=3000.0, age=55}] 管理部门按照age(年龄)降序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=4, name='af', sal=800.0, age=19}] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 通过匿名内部类来比较排序对象 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 考勤部门按照name(名称)升序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=2, name='as', sal=2000.0, age=44}] 考勤部门按照name(名称)降序排序 [Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=1, name='ad', sal=3000.0, age=55}] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 通过Lambda表达式来比较排序对象 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 考勤部门按照name(名称)降序排序 [Teacher{id=2, name='as', sal=2000.0, age=44}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=1, name='ad', sal=3000.0, age=55}] 考勤部门按照name(名称)升序排序 [Teacher{id=1, name='ad', sal=3000.0, age=55}, Teacher{id=3, name='ae', sal=1000.0, age=22}, Teacher{id=5, name='ae', sal=1100.0, age=33}, Teacher{id=4, name='af', sal=800.0, age=19}, Teacher{id=2, name='as', sal=2000.0, age=44}] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>