一。比较器
作用:比较大小的
Collections.sort(List<?> list)
如果调用该功能,那么我们需要注意,
这个功能 采用默认的比较规则进行对象之间的比较排序。
什么是默认的规则呢,这就要求集合中的元素类型
去实现一个叫做Comparable接口,其实是为了实现里面
compareTo()功能,这个功能中就定义了比较的规则。
那么反过来 如果集合中元素类型 没有实现Comparable比较器,那么就不能这样去用
如果这样去用 会编译报错,这个一会存储自定义类的时候来演示。
比较器有两种
内比较器 Comparable
他是让对象自身具备比较的功能
外比较器 Comparator
可以理解为一个工具,是用来对对象比较的工具。
如果你同时可以使用内比较器和外比较器,会将内比较器给屏蔽,我们使用的是外比较器。
如果我们要进行对象间的比较,那么就需要实现比较器接口,内比较器,外比较器
java提供了两种 比较规则 的实现
一种 在定义类的时候,进行对java.lang.Comparable接口进行实现,并且完成对compareTo方法的实现
比较的规则就定义在compareTo方法中,比如String,Integer等类
另外一种比较灵活,你可以在定义类的时候不去实现内比较器接口,在需要比较的地方,直接去实现比较
的规则就可以,怎么实现比较规则呢,其实JDK中方法,它会需要一个参数 Comparator接口,我们一般写
匿名内部类完成,其实关注的不是接口不是对象,而是比较的规则,这个接口中就需要你重写一个规则方法
compare方法
区别
内比较器 Comparable
比较方法
compareTo(T t)
以比较数字类型来说
当前的-传进来的的 升序
传进来的-当前的 降序
什么时候用的呢? 一个类定义的时候实现内比较器。
当一个类定义的时候就已经产生了比较的规则,实现了Comparable即可并完成conpareTo方法的定义
实现这个接口的类 天生就具备了比较的规则 但是这种定义比较固定 不灵活
适用于永远不改变的规则
外比较器 Comparator
比较方法
compare(T t1,T t2)
以数字为例
t1数字值-t2数字值 升序
t2数字值-t1数字值 降序
1:它适用于原来我的类没有比较的规则,而现在我需要进行比较,想要进行比较,只能利用这个外比较器接口
进行比较 Collections.sort(List<T> list,new 匿名内部类 )重点是完成比较的规则
2:原有的比较规则,不喜欢了,或者不适用当前的场景了,而有不能改源码,那么在使用的地方临时修改成
最新的规则 那么可以采用外比较器的方式。
内比较器和外比较器实现的功能都是一样的。只不过实现的方式不一样。
无论是内比较器或者外比较器,实现的方法都是int类型的值:
有三个情况:
> 0 :是一个对象的属性值大于了另外一个对象的属性值。
如果是正序:在后面
如果是倒序:在前面
== 0 :两个比较的结果是相等的, 正常添加
< 0 :是一个对象的属性值小于了另外一个对象的属性值。
如果是正序:在前面
如果是倒序:在后面
public class Demo03Sort {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("马尔扎哈",17));
list.add(new Student("a尔扎哈",17));
list.add(new Student("古力娜扎",16));
list.add(new Student("迪丽热巴",18));
System.out.println("排序前:"+list);
//排序规则是 按照年龄降序排列
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int temp = o2.getAge()-o1.getAge();//按照年龄进行降序排列
//按照姓名进行升序排列
temp = (temp == 0) ? o1.getName().compareTo(o2.getName()) : temp;
return temp;
}
});
System.out.println("排序后:"+list);
}
}
二.Map<K,V> :双列集合的根接口
K:键 -> 是唯一的
Va:值 -> 可以重复
键和值得关系是映射,一个键映射一个值。
HashMap<K,V> :
底层是使用哈希表结构,Map集合是以键为主,键是唯一的,而且存储元素是无序。
底层算法和HashSet集合是同一套算法。实现方式也是一样。包装Map集合中的键唯一:
需要去重新hashCode和equals方法。
特点:
1:键唯一 值可以重复
2:键和值一一映射 也就是一个键对应一个值
3:通过键找到值 (通过键维护关系)
常见的子类
HashMap<K,V>
LinkedHashMap<K,V>:可以保证存和取得顺序是一致的
常见的方法
public V put(K key,V value) :将指定的键与对应的值 存储到Map集合中
如果key在集合中没有,那么添加一个新的键
如果key代表的键在集合中已经存在,那么会将原有的值给覆盖掉。
V:被替换的值。如果是第一次添加返回的是null
public V remove(Object key) : 通过指定的键 删除其在Map中的映射关系 返回被删除的映射关系中的值
返回的是被删除键映射的值
public int size() 获取 Map集合中 存储的 映射关系 有几个
public Set<K> keySet() : 获取键集 (就是所有键的集合 Set)
public Collection<V> values : 获取值集
public V get(Object key) :根据键找对应的值
返回的是,键对应的值。
public boolean containsKey(Object obj):判断指定键是否存在
面试题:
HashMap 和 Hashtable :
HashMap可以存储null键和null值
线程不安全的,效率高
Hashtable 不可以存储null键和null值
线程安全的,效率低。
eg:
Map<String,String> map = new HashMap<>();
map.put(null,null);
map.put("aaa",null);
System.out.println(map);
Hashtable<String,String> table = new Hashtable<String,String>();
table.put(null,null); //NullPointerException异常
table.put("aaaa",null); //NullPointerException异常
System.out.println(table);
a> Map集合的遍历方式:
1.通过Map中的 Set<K> keySet();获取所有的键
通过对Set集合进行遍历,拿到每一个键,通过Map集合中 V get(Object k);
b> 接口 Map.Entry<K,V>
K getKey()
返回与此项对应的键。
V getValue()
返回与此项对应的值。
c> 如何获取Map集合中的Entry对象。
在Map集合中有个方法可以获取: Set<Map.Entry<K,V>> entrySet();
Map集合遍历方式二
通过键值对对象方式遍历
思路
1:通过entrySet方法,获取所有的Entry(键值对)对象,存放在Set集合中
2:遍历Set集合 得到每一个Entry对象
3:根据对应方法 获取每一个Entry中对应的键与对应的值
d> Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。
新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。
of(...)方法 重载方法
1:of()方法只是Map,List,Set这三个接口的静态方法,
其父类接口和子类实现并没有这类方法,比如 HashSet,ArrayList等;
2: 返回的集合是不可变的;
e> Debug调试
1:加断点
2:debug模式执行
3:追踪
左侧 是 正在运行的方法
代码向下执行一行 快捷键F8
进入要调用的方法中 快捷键 F7
运行完所有程序 快捷键F9
停止Debug模式 快捷键 ctrl+F2
切换控制台Console 查看运行操作结果
右侧
变量值 显示区域
f> 将set转换成list集合进行遍历(两种方法)
A: ArrayList<Integer> list = new ArrayList<>();
list.add(setName);
B: ArrayList<Integer> list = new ArrayList<>(setName);