一、Collections类
1、概述
前面学习了Collection集合,这不是一样的?Collection不是一个接口吗?现在这么又是一个类了呢?这里值得注意的是,Collection是一个接口没错,不过现在讲的是Collections,末尾多了一个s,虽然看起来很像,不过它们是有区别的;Collections是java.util包下面的一个类。
Collectiongs类不能创建对象,虽然它是一个类,但是它的构造方法是私有化的,所以无法创建对象;
Collectiongs类里面的方法都是静态的,所以在使用Collections里面的方法时,直接使用类名点方法名调用就可以了。
Collections类里面常用的方法有:
public static void shuffle(List<?> list) 打乱集合顺序。
public static <T extends Comparable<? super T>> void sort(List<T> list) 将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> ) 将集合中元素按照指定规则排序。
public static <T> boolean addAll(Collection<T> c, T... elements) 往集合中添加一些元素。
2、乱序方法
先看乱序方法:public static void shuffle(List<?> list)
这个方法是把一个List集合里面的元素乱序,也就是随机排序,但是参数只能是List集合;
看测试代码:
public static void main(String[] args) { //创建一个ArrayList集合 ArrayList<Integer> integers = new ArrayList<>(); //添加一些元素 for (int i = 1;i<11;i++){ //这里传入一个int类型的数据,系统会自动装箱,把int类型的数据包装成Integer的对象 integers.add(i); } //先输出乱序之前的顺序 for (Integer integer : integers) { System.out.print(integer+" "); } //乱序 Collections.shuffle(integers); //再输出乱序之后的顺序 System.out.println("\n-----乱序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); } }
运行结果是:
结果很明显,List集合是有序的,可以保证元素的存入顺序就是取出顺序,所以在乱序前按顺序输出1到10,使用Collections类里面的shuffle方法后,再次遍历输出,集合的顺序里面开始存入的元素的顺序就被打乱了。
3、排序方法
public static <T extends Comparable<? super T>> void sort(List<T> list) 将集合中元素按照默认规则排序。
诶,这个方法有点奇怪啊,”<T extends Comparable<? super T>>“这一段语句是什么意思啊,以前定义方法的时候好像没见过,它的意思是对T的约束是Comparable的子类,对Comparable中泛型的约束是,?至少是T的父类,那么就意味着T是?的子类。一言以蔽之:元素必须是实现了Comparable接口的类或者其子类,可以使用父类方法比较子类型。我们使用系统提供的数据类型类都是继承了Comparable接口的,所以才可以比较,如果我们要在集合里面存自己写的类,然后需要用到排序方法时就必须要实现Comparable接口,重写实现里面的compareTo方法,定义好排序的规则,才可以使用Collections类里面的sort方法进行排序
看代码
//现在测试按默认规则排序的方法 Collections.sort(integers); System.out.println("\n-----排序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); }
运行结果:
此时我们发现,按找默认规则排序后的集合里面的元素又变的有序了,那它是按哪种规则排序的呢?暂时不管,我们继续往下面看
public static <T> void sort(List<T> list,Comparator<? super T> ) 将集合中元素按照指定规则排序。仔细一看,诶,这个方法是重载方法,这个方法的第一个参数我能看懂,就是传入一个List集合嘛,第二个参数是什么意思呢?传入一个Comparator对象吗?不是的,这是要传入一个Comparator的实现类的对象,诶,那问题来了,我又要重新写一个类来定义排序规则吗?其实是没有必要的,这里告诉大家一个新知识:匿名内部类,看代码:
//测试自定义规则排序 //第一个参数就是传入一个List的实现类对象,第二个参数可以直接使用匿名内部类 //不需要把类完整写一遍,直接在传参的时候实现接口即可 Collections.sort(integers, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { //定义了排序规则,o1-o2就是升序,即从小到大 //那反过来用o2-o1就是降序了,从大到小啰 return o2-o1; } }); System.out.println("\n-----自定义规则排序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); }
代码运行结果:
这时我们发现,顺序从大到小了,再回到前面那个默认排序,为什么它是默认从小到大呢?看看Integer类的源码:
看,它这里呢是使用了三元运算符,x<y就返回-1,即返回一个负数,和我们用o1减o2是不是一样的道理呢?x不小于y再看是不是相等,相等返回0,不相等就返回1,即一个正数,之后sort方法再根据这个数去给元素排序,这样即可实现自定排序。
二、Map集合
1、概述
现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即
java.util.Map
接口。
2、常用子类
通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。
HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
tips:Map接口中的集合都有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同。
3、常用方法
Map接口中定义了很多方法,常用的如下:
public V put(K key, V value)
: 把指定的键与指定的值添加到Map集合中。
public V remove(Object key)
: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
public V get(Object key)
根据指定的键,在Map集合中获取对应的值。
public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。
public boolean containKey(Object key)
:判断该集合中是否有此键。
4、遍历Map集合的遍历
Map集合的遍历可以使用entry对象来遍历,也可以使用get方法来遍历,不过,这里的get方法的参数不是索引,而是键
常用方法的演示就放在这里了,代码如下:
public static void main(String[] args) { //这里使用HashMap进行测试 //创建一个HashMap对象 HashMap<String, String> strHashMap = new HashMap<>(); //添加元素的put方法 strHashMap.put("王哥","煤老板"); strHashMap.put("李哥","包工头"); strHashMap.put("陈哥","项目经理"); strHashMap.put("周哥","超市老板"); strHashMap.put("赵哥","税务局局长"); strHashMap.put("蒋哥","股东"); //测试get方法,get方法的返回值类型就是值的数据类型 System.out.println(strHashMap.get("王哥")); System.out.println("------分割线------\n此时代表get方法和put方法使用成功"); //测试keyset方法,该方法返回Map集合键的Set集合 //遍历键的集合,依次获取值,达到遍历输出的目的 for (String s : strHashMap.keySet()) { System.out.println(s+"的职业是"+strHashMap.get(s)); } //测试remove方法,该方法通过键来删除元素,返回被删除的元素的值 System.out.println("------遍历元素分隔线------"); System.out.println(strHashMap.remove("王哥")); System.out.println("-----删除元素后的分隔线-----"); //测试entrySet方法,该方法返回键值对的Set集合 //使用该方法遍历集合 for (Map.Entry<String, String> entry : strHashMap.entrySet()) { System.out.println(entry.getKey()+"的职业是"+entry.getValue()); } System.out.println("此时王哥-煤老板这一键值对已被删除"); //最后测试一下containsKey方法 System.out.println(strHashMap.containsKey("王哥"));//王哥这个键已经被删除,所以返回false System.out.println(strHashMap.containsKey("李哥"));//键里面有李哥这个键,所以返回true } public static void collectionsTest(){ //创建一个ArrayList集合 ArrayList<Integer> integers = new ArrayList<>(); //添加一些元素 for (int i = 1;i<11;i++){ //这里传入一个int类型的数据,系统会自动装箱,把int类型的数据包装成Integer的对象 integers.add(i); } //先输出乱序之前的顺序 for (Integer integer : integers) { System.out.print(integer+" "); } //乱序 Collections.shuffle(integers); //再输出乱序之后的顺序 System.out.println("\n-----乱序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); } //现在测试按默认规则排序的方法 Collections.sort(integers); System.out.println("\n-----排序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); } //测试自定义规则排序 //第一个参数就是传入一个List的实现类对象,第二个参数可以直接使用匿名内部类 //不需要把类完整写一遍,直接在传参的时候实现接口即可 Collections.sort(integers, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { //定义了排序规则,o1-o2就是升序,即从小到大 //那反过来用o2-o1就是降序了,从大到小啰 return o2-o1; } }); System.out.println("\n-----自定义规则排序前后分隔线-----"); for (Integer integer : integers) { System.out.print(integer+" "); } }
最后来看看运行结果: