Comparator比较器 Comparable接口 Map集合
今日内容:
-
Comparator比较器
-
Comparable接口
-
Map集合
学习目标:
-
能够描述Comparable接口和Comparator接口的区别
-
会自定义Comparable接口和Comparator接口比较器比中的比较规则
-
能够说出Map集合的特点
-
使用Map集合添加方法保存数据
-
使用“键找值”的方式遍历Map集合
-
使用“键值对”的方式遍历Map集合
-
能够使用HashMap存储自定义键值对的数据
-
能够使用HashMap编写一些小型案例。
-
Comparator接口比较器
Collections工具集中的sort()
public static <T> void sort(List<T> list)
public static <T> void sort(List<T> list,Comparator<? super T> c)
Comparator接口在java.util包下面,排序是Comparator需要实现的功能之一,
该接口代表的是是一个比较器,比较器具有可比性,可以做排序的,
本质其实比较两个对象谁排在前边谁排在后边。
那么比较的方法是:
public int compare(Object o1,Object o2):比较两个参数的的顺序
两个对象比较的结果有三种:大于,等于,小于
如果要按照升序排序:则o1小于o2返回(负数),相等返回0,o1大于o2返回(正数)
如果要按照降序排序:则o1小于o2返回(正数),相等返回0,o1大于o2返回(负数)
简化操作:
升序排序: o1-o2
降序排序: o2-o1
public static void main(String[] args) {
//public static <T> void sort(List<T> list)
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("cba");
list.add("bca");
list.add("sba");
list.add("nba");
// 排序规则,按照字符串的第一个字母降序排序
// 使用接口中的方法:
// public static <T> void sort(List<T> list,Comparator<? super T> c)
// public int compare(Object o1,Object o2):比较两个参数的的顺序
Collections.sort(list,new Comparator(){
@Override
public int compare(String o1,Strng o2) {
/*if(o2.charAt(0) - o1.charAt(0) > 0){
return 1;
} else if ( o2.charAt(0) - o1.charAt(0) == 0){
return 0;
} else {
return -1;
}*/
return o2.charAt(0) - o1.charAt(0);
}
});
System.out.println(list);
}
// 控制台结果:
[sba,nba,cba,bca,abc]
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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 age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class MainClass {
public static void main(String[] args) {
// 假如学生都是老外 名字都是字母
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("tom",20));
list.add(new Student("lily",18));
list.add(new Student("jack",26));
list.add(new Student("rose",40));
list.add(new Student("smith",26));
// 按照年龄升序排序
// 如果年龄相同的话,然后按照姓名排序,按照姓名的首字母降序排序
// 嵌套比较
// o1 - o2 代表升序
// o2 - o1 代表降序
Collections.sort(list,new Comparator<Student>(){
@Override
public int compare(Student o1,Student o2) {
int num = o1.getAge() - o2.getAge();
if( num == 0) {
num = o2.getName().charAt(0) - o1.getName().charAt(0);
}
return num;
}
});
System.out.println(list);
// [Student{name='lily', age=18}, Student{name='tom', age=20}, Student{name='smith', age=26},
// Student{name='jack', age=26}, Student{name='rose', age=40}]
}
}
简述Comparable和Comparator两个接口的区别
Comparable:强行对实现它的每个类对象进行整体排序。这种排序我们一般把它称之为自然排序,类的compareTo方法被称之为它的自然比较方法。只能在类中实现compareTo方法一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort()(和Arrays.sort())进行自动排序,对象可以用作有序映射中的键或者有序集合中的元素,无需指定比较器。
Comparator:强行对某个对象进行整体排序。可以将Comparator传递给sort()方法(如Collections.sort()后者Arrays.sort()),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(有序的set或者是有序的映射)的顺序,或者为那些没有自然顺序的对象Collection提供排序。
public class Student{
private String name;
private int age;
// get和set方法
// toString方法
// 无参构造和全参构造
}
public class MainClass {
public static void main(String[] args) {
// 假如学生都是老外 名字都是字母
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("tom",20));
list.add(new Student("lily",18));
list.add(new Student("jack",26));
list.add(new Student("rose",40));
list.add(new Studeng("smith",26));
// 按照年龄升序排序
// 如果年龄相同的话,然后按照姓名排序,按照姓名的首字母降序排序
Collections.sort(list,new Comparator(){
@Override
public int compare(Student o1,Student o2) {
int num = o1.getAge() - o2.getAge();
if( num == 0) {
num = o2.getName().charAt(0) - o1.getName().charAt(0);
}
return num;
}
})
System.out.println(list);
}
}
// 控制台输出的结果:
[Student("lily",18),Student("tom",20),Student("jack",26),Student("rose",40)]
// 二次控制台输出结果:
[Student("lily",18),Student("tom",20),Studeng("smith",26),Student("jack",26),Student("rose",40)]
Map集合
现实生活中,我们常会看到这样一种集合:IP地址和主机名,身份证号和个人,系统用户名与系统用户对象等,这种一一对应的关系,我们把它称之为映射。Java当中提供了专门的集合类用来存放这种映射关系的对象。
即java.util.Map
接口。通过如下图发现Collection接口集合和Map接口集合存储数据的方式不一样。
HashMap集合的特点:
1. HashMap集合底层是哈希表:查询的速度非常快
JDK1.8之前:数组+链表结构
JDK1.8之后:数组+链表/红黑树(当链表长度超过8):提高查询性能
2. HashMap集合是一个无序集合,存取顺序可能不一致
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
LinkedHaspMap集合特点:
1、LinkedHaspMap集合底层是哈希表+链表(保证迭代的顺序)
2、LinkedHaspMap集合是一个有序的集合,存取元素的顺序是一致的。
Map集合当中的常用API方法
- 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集合当中的所有的key值,存储到Set集合当中
- public Set<Map.Entry<K,V>> entrySet():获取到Map集合当中的所有的键值对对象的集合(Set集合)
public class Demo01Map {
public static void main(String[] args) {
show03();
}
/*
public V get(Object key):根据指定的键 获得在Map集合当中对应的值
返回值:
key存在,返回对应的value值
key不存在,返回null
*/
public static void show03() {
Map<String,Integer> map = new HashMap<>();
map.put("小孙", 30);
map.put("小王", 25);
map.put("小赵", 18);
map.put("小刘", 19);
System.out.println("-----------------------");
System.out.println(map);// {小孙=30, 小刘=19, 小王=25, 小赵=18}
// 使用get方法
Integer v1 = map.get("小孙");
System.out.println(v1);// 30
Integer v2 = map.get("老王");
System.out.println(v2);// null
}
/*
public V remove(Object key):把指定的键所对应的键值对元素从Map集合当中删除,返回被删除元素的值
返回值V
key存在,返回的是删除的对应的value值
key不存在,返回null
*/
public static void show02() {
Map<String,Integer> map = new HashMap<>();
map.put("小孙", 30);
map.put("小王", 25);
map.put("小赵", 18);
map.put("小刘", 19);
System.out.println("-----------------------");
System.out.println(map);// {小孙=30, 小刘=19, 小王=25, 小赵=18}
// 使用remove方法
int v01 = map.remove("小孙");// 自动拆箱
System.out.println(v01);// 30
System.out.println("---------------------------");
System.out.println(map);
int v02 = map.remove("小李"); // NullPointerException
System.out.println(v02);//null
Integer int01 = 30;
// int num01 = 30
//int i = int01.intValue();
// 建议使用包装类型 整数 浮点数 字符 布尔
}
/*
public V put(K key,V value):把指定的键与指定的值添加到Map集合当中
返回值是V
存储键值对的时候,key不重复,返回值V是null
存储键值对的时候,key重复,会使用新的value值替换掉Map集合中原来的value值,返回的是被替换的value值
*/
public static void show01() {
//使用多态
Map<String,String> map = new HashMap<>();
String v01 = map.put("小孙", "小丽");
System.out.println(v01);// null
String v02 = map.put("小孙", "小花");
System.out.println(v02);// 小丽
System.out.println("==================");
System.out.println(map);// {小孙=小花}
map.put("小王", "小丽");
map.put("小赵", "小美");
map.put("小刘", "小芳");
System.out.println("-----------------------");
System.out.println(map);// {小孙=小花, 小刘=小芳, 小王=小丽, 小赵=小美}
}
}
- Collection中的集合,元素是孤立存在的(单身),向集合中存储元素采用一个一个元素存储的方式进行存储。
- Map中的集合,元素是成对存在的(夫妻),每个元素由键和值两部分组成。通过键可以找到对应的值。
- Collection中的集合我们称之为单列集合,Map中的集合我们称之为双列集合
- 注意:Map中的集合不能包含重复的键,值可以重复,每个键对应唯一一个值。
#### Map中的常用子类
通过查看API帮助文档发现有很多个子类,我们主要介绍HashMap集合、LinkedHaspMap集合、HashTable集合
- HashMap:存储数据采用的哈希表结构,元素的存取顺序可能不一致,由于要保证键的唯一性,不重复,需要重写键的hashCode方法和equals方法。
- LinkedHashMap:HashMap下面有个子类LinkedHashMap,存储数据的方式是采用哈希表结构+链表结构,通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证键的唯一、不重复,需要重写键的hashCode方法和equals方法。
备注:Map接口当中,含有两个泛型变量,在使用时,要为两个泛型变量赋予数据类型,两个泛型变量的数据类型可以相同,也可以不同。
#### Map接口当中的常用API方法Map<K,V>
常用方法如下:
- 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集合当中的所有的key值,存储到Set集合当中
- public Set<Map.Entry<K,V>> entrySet():获取到Map集合当中的所有的键值对对象的集合(Set集合)
-
Map集合中的第一种遍历方式: 通过键找值的方式
Map集合中的方法:
public Set<K> keySet(): 获取Map集合当中的所有的key值,存储到Set集合当中
实现步骤:
1.使用Map集合当中的keySet方法,把Map集合当中的所有的key值,存储到Set集合当中
2.遍历Set集合,获取Map集合当中的每一个key值
3.通过Map集合当中的方法get(key),通过key找到value
public class Demo02KeySet {
public static void main(String[] args) {
// 创建map集合对象
Map<String,Integer> map = new HashMap<>();
map.put("迪丽热巴", 178);
map.put("古力娜扎", 164);
map.put("马尔扎哈", 160);
map.put("撒有哪啦", 150);
// 使用Map集合当中keySet方法,把Map集合当中的所有的key值,存储到Set集合当中
Set<String> sets = map.keySet();
// 遍历Set集合 采用迭代器或者增强for循环
Iterator<String> iterator = sets.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Integer value = map.get(key);
System.out.println(key + "=" + value);
//迪丽热巴=178
//撒有哪啦=150
//古力娜扎=164
//马尔扎哈=160
}
System.out.println("--------------------------------------");
// 使用增强for循环
for (String key : sets) {
Integer value = map.get(key);
System.out.println(key + "=" + value);
}
System.out.println("--------------------------------------");
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + "=" + value);
}
}
}
Map集合遍历的第二种方式:使用Entry对象遍历
Map集合当中的方法:
public Set<Map.Entry<K,V>> entrySet():获取到Map集合当中的所有的键值对对象的集合(Set集合)
实现步骤:
1.使用Map集合中的方法entrySet(),把Map集合当中的多个Entry对象取出来,存储到一个Set集合当中
2.遍历Set集合,获取每一个Entry对象
3.使用Entry对象中的方法getKey()和getValue()分别获取map集合当中的键与值
public class Demo03EntrySet {
public static void main(String[] args) {
// 创建一个Map集合对象
Map<String, Integer> map = new HashMap<>();
map.put("孙大圣", 150);
map.put("孙行者", 160);
map.put("者行孙", 170);
map.put("行者孙", 175);
// 1.使用Map集合中的方法entrySet(),把Map集合当中的多个Entry对象取出来,存储到一个Set集合当中
Set<Map.Entry<String, Integer>> set = map.entrySet();
// 2. 遍历Set集合,获取每一个Entry对象
// 使用迭代器遍历Set集合
Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
while (iterator.hasNext()) {
// 取出下一个元素
Map.Entry<String, Integer> entry = iterator.next();
// 3.使用Entry对象中的方法getKey()和getValue()分别获取map集合当中的键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "=" + value);
// 者行孙=170
// 孙行者=160
// 孙大圣=150
// 行者孙=175
}
}
}
上一篇: JAVA集合中泛型的原理本质简介
下一篇: Android 获取屏幕和控件大小
推荐阅读
-
java比较器Comparable接口与Comaprator接口的深入分析
-
java比较器Comparable接口与Comaprator接口的深入分析
-
Map集合的遍历方式以及TreeMap集合保存自定义对象实现比较的Comparable和Comparator两种方式
-
【java读书笔记】——Collection集合之六大接口(Collection、Set、List、Map、Iterator和Comparable)
-
Java 两种比较器的区别:Comparable 与 Comparator
-
Comparable和Comparator两个比较器,map集合
-
Java比较器——Comparable接口和Comparator接口
-
【小家Java】聊聊Java中的比较器(排序):Comparable和Comparator;Spring中的Comparators和AnnotationAwareOrderComparator
-
深入浅出了解java比较器 区分Comparable与Comparator的差异以及对象数组的排序
-
java常用类库---比较器(Comparable,Comparator)