学了这么长时间的集合,是否会对这三大集合进行排序呢?
首先,了解一下Comparator和Comparable
通常,要对一个存储在集合内的实体类进行排序时,有两种策略:1. 实体类实现Comparable接口;2. 创建集合时指定Comparator,即实现Comparator接口;
为了区分这两个接口,通过称实现Comparable的实体类是可排序的,而Comparator则称呼为比较器。
下面使用具体的代码来使用这两个接口(按照使用的集合分别进行讲解)
List
List中存储的是Integer等数据类型的话,直接使用Collections.sort(List<E> list)
或者Collections.sort(List<E> list, Comparator<? super T> c)
进行排序。这里讲的是自定义类的排序。
- 实现Comparable的方式
package sort.list;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @ClassName Demo2
* @Description: 按照User的年龄进行排序
* @Author 田清波
* @Mail tqb820965236@163.com
* @Date 2019/8/13 16:34
* @Version v1.0
*/
public class Demo2 {
@Test
public void test(){
User user1 = new User("zhangsan", 23);
User user2 = new User("lisi", 25);
User user3 = new User("wangwu", 20);
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
System.out.println("未排序:" + list);
Collections.sort(list);
System.out.println("已排序:" + list);
}
}
class User implements Comparable<User>{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(User o) {
/**
* 指定对象减去此对象 - 降序
* 此对象减去指定对象 - 升序
*/
// System.out.println(o.age - this.age);
return this.age - o.age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 实现Comparator的方式
package sort.list;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @ClassName Demo2
* @Description: 按照User的年龄进行排序
* @Author 田清波
* @Mail tqb820965236@163.com
* @Date 2019/8/13 16:34
* @Version v1.0
*/
public class Demo2 {
@Test
public void test(){
User user1 = new User("zhangsan", 23);
User user2 = new User("lisi", 25);
User user3 = new User("wangwu", 20);
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
System.out.println("未排序:" + list);
/**
* 通过匿名内部类进行实现,即指定排序的方式
*/
Collections.sort(list, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
/**
* o2 - o1 : 降序
* o1 - o2 : 升序
*/
return o2.getAge() - o1.getAge();
}
});
System.out.println("已排序:" + list);
}
}
class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Set
这里以我春招面试途牛的一道题作为讲解,当时真的不会,所以自然面试没通过(=_=),下来做了一下非常的懊悔!!!
题目:
现在存在这么个需求,就是对学生进行排序操作(升序降序都实现),前提是不能存在相同年龄的学生(当然我觉得这是不合理的)在进行学生添加的时候,相同年龄不再进行添加。
解决思路:
1. 首先使用Set集合(Set集合不允许出现相同的数据,即数据唯一,TreeSet(使用该类添加自定义的实体类时,要么实现可排序接口,要么自定义比较器)这里需要知道TreeSet的存储结构数据是排好序的。
2. 用户Person实现equals(供用户调用)和hashcode方法(在进行数据add的时候,默认调用hashcode方法)
3. hashcode通过age计算hash值,这样保证了数据的唯一性
4. 排序的话两种实现方式
1. Person实现可排序接口Comparable
2. 创建集合时指定比较器
代码体现:
package sort.set;
import org.junit.Test;
import java.util.*;
/**
* @ClassName SetToList
* @Description: 途牛面试题
* @Author 田清波
* @Mail tqb820965236@163.com
* @Date 2019/8/13 21:20
* @Version v1.0
*/
public class SetToList {
@Test
public void test(){
Set<Person> set = new TreeSet<>(new Comparator<Person>() {
/**
* 原先的排序方式失效(升序)
* @param o1
* @param o2
* @return
*/
@Override
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();// 降序
}
});
Person person1 = new Person("zhangsan" ,11);
Person person2 = new Person("lisi" ,14);
Person person3 = new Person("wangwu" ,13);
Person person4 = new Person("lisi" ,13);
set.add(person1);
set.add(person2);
set.add(person3);
set.add(person4);
System.out.println(set.size());
System.out.println(set);
}
}
class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
/**
* 重写equals和hashCode方法
* 判断是否是一个对象
* (途牛面试题目,当时真的不会做)
* 题目:现在存在这么个需求,就是对用户进行排序操作(升序降序都实现),前提是不能存在相同年龄的用户(当然我觉得这是不合理的)
* 在进行用户添加的时候,相同年龄不再进行添加。
* 解决思路:
* 首先使用Set集合(Set集合不允许出现相同的数据,即数据唯一,TreeSet(使用该类添加自定义的实体类时,要么实现可排序接口,要么自定义比较器) 数据是排序的)
* 用户Person实现equals(供用户调用)和hashcode方法(在进行数据add的时候,默认调用hashcode方法)
* hashcode通过age计算hash值
* 这样保证了数据的唯一性
* 排序的话两种实现方式
* 1. Person实现可排序接口Comparable
* 2. 创建集合时指定比较器
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!(o instanceof Person))
return false;
Person person = (Person) o;
return person.age == this.age;
}
/**
* 对象相同的话,哈希值一定相同
* 对象不相同的话,哈希值不一定不相同(存在哈希碰撞)
* 依靠这个性质判断对象是否相同
* 供散列表进行调用 HashSet HashMap...
* @return
*/
@Override
public int hashCode() {
return Objects.hash(age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
@Override
public int compareTo(Person o) {
return this.age - o.age; // 升序
}
*/
}
Map
题目:按照水果的个数进行排序
直接上代码(还可以使用List进行实现,即针对List进行排序再转换,这里直接使用TreeSet,TreeMap也可以实现):
package sort.map;
import org.junit.Test;
import java.util.*;
/**
* @ClassName MapSort
* @Description: 对Map进行排序
* @Author 田清波
* @Mail tqb820965236@163.com
* @Date 2019/8/15 9:02
* @Version v1.0
*/
public class MapSort {
@Test
public void test(){
HashMap<Fruit, Integer> map = new HashMap<>();
Fruit fruit1 = new Fruit("苹果");
Fruit fruit2 = new Fruit("草莓");
Fruit fruit3 = new Fruit("梨");
Fruit fruit4 = new Fruit("西瓜");
Fruit fruit5 = new Fruit("香蕉");
map.put(fruit1, 9);
map.put(fruit2, 2);
map.put(fruit3, 8);
map.put(fruit4, 5);
map.put(fruit5, 1);
Map<Fruit, Integer> sort = sort(map);
Set<Map.Entry<Fruit, Integer>> entries = sort.entrySet();
for (Map.Entry<Fruit, Integer> entry : entries){
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
public Map<Fruit, Integer> sort(Map<Fruit, Integer> map){
/**
* 将Map转为Set
*/
Set<Map.Entry<Fruit, Integer>> entries = map.entrySet();
TreeSet<Map.Entry<Fruit, Integer>> set = new TreeSet<>(new Comparator<Map.Entry<Fruit, Integer>>() {
@Override
public int compare(Map.Entry<Fruit, Integer> o1, Map.Entry<Fruit, Integer> o2) {
return o1.getValue() - o2.getValue();
}
});
/**
* 向TreeSet中添加数据
*/
for (Map.Entry<Fruit, Integer> entry : entries){
set.add(entry);
}
/**
* 将Set转为LinkHashMap(有序)返回
*/
LinkedHashMap<Fruit, Integer> resMap = new LinkedHashMap<>();
for (Map.Entry<Fruit, Integer> entry : set){
resMap.put(entry.getKey(), entry.getValue());
}
return resMap;
}
}
class Fruit {
private String name;
private String remark;
public Fruit() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Fruit(String name) {
this.name = name;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", remark='" + remark + '\'' +
'}';
}
}