16.Map系列、集合排序、不可变集合

一.Map

1.1 Map集合概述

Map集合是一种双列集合,每个元素包含二个数据。非常适合购物车这类业务场景。

1.2 Map集合体系

1.3 Map集合特点

Map集合体系特点

  • Map集合的特点都是由键决定的

  • Map集合的键是无序、不重复、无索引的、值不作要求。

  • Map集合后面重复的键对应的值会覆盖前面重复键的值。

  • Map集合的键值对都可以为null。

Map集合实现类特点

  • HashMap:元素是按照键无序、不重复、无索引,值不做要求。

  • LinKedHashMap:元素是按照键有序、不重复、无索引,值不做要求。

  • TreeMap:元素是按照键排序、不重复、无索引,值不做要求。

1.4 Map集合的API

Map集合是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。

1.5 Map集合的遍历方式

键找值的方式遍历

  1. 先获取Map集合的全部键的Set集合

  2. 遍历键的Set集合,然后通过键提取对应值。

键找值涉及到的API:

键值对的方式遍历

  1. 先把Map集合转换成Set集合,Set集合中的每个元素都是键值对实体类型了。

  2. 遍历Set集合,然后提取键以及提取值。

键值对遍历涉及到的API

Lambda表达式的方式

得益于JDK8开始的新技术Lambda表达式,提供了一种更简单更直接的遍历方式。Lambda表达式遍历涉及到的API

1.6 HashMap

1.7.1 HashMap的特点

无序、不重复、无索引。

1.7.2 底层原理

HashMap 的底层原理和 HashSet 是一样的,都是哈希表,所以元素的增删改查性能都很好。

1.7.3 注意事项

  • Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。

  • 依赖equals和hashcode方法保证键的唯一。

  • 如果键要存储的是自定义对象,需要在对象中重写equals和hashcode方法。

1.8 LinkedHashMap

1.8.1 特点

有序、不可重复、无索引。

1.8.2 原理

同LinkedHashSet一样,底层数据结构依然是哈希表,只是每个键值对元素又多了一个双链表的机制记录存储的顺序。元素的增删改查性能也很好。

1.8.3 注意事项

同HashMap

1.9 TreeMap

1.9.1 特点

排序,不可重复,无索引

1.9.2 排序规则

具有值特性的数据默认按照键升序排序。

自定义类型的对象有二种方式排序:

  • 类实现Comparable接口,重写比较规则。

  • 集合自定义Comparator比较器对象,重写比较规则。

1.9.3 底层原理

同HashSet一样,底层是红黑树,所以元素的增删改查性能很好。

1.9.4 注意事项

TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序

二.集合排序

2.1 集合排序概述

Collections类

Collections类是集合的工具类,可以对List集合进行排序,无法直接对Set、Map类型的集合进行排序,在排序过程中依赖于Comparable、Compatator接口。该类除了排序还有许多其他功能,例如对集合元素:查找,排序,洗牌,转换,拷贝,查找最大值/最小值,集合反转,安全集合的获取等一系列静态方法。

Comparable<T>和Comparator<T>接口

Comparable<T>和Comparator<T>是Java用来对集合进行排序的二个接口。通过重写这二个接口中的方法,可以指定具体的排序规则对集合中的对象进行排序。Comparator 既可以让对象实现此接口实现定制排序,也可以通过匿名内部类的方式传入Collections、TreeSet、TreeMap等集合类中来实现定制排序。

Note:对于String、Integer等类已经默认实现了Comparable接口了

2.2 List类型集合的排序

2.1.1 Comparable:自然排序

第一步:创建实体类实现 Comparable 接口,实现其ComparaTo(T t)方法。

public class Student implements Comparable<Student>{
 
    private int sno;
    private String sname;
    private String sex;
    private String major;
    private Date birth;
    private double score;
 
    public Student(int sno, String sname, String sex, String major, Date birth, double score) {
        this.sno = sno;
        this.sname = sname;
        this.sex = sex;
        this.major = major;
        this.birth = birth;
        this.score = score;
    }
 
    /**
     *   自然排序的比较方法
     */
    @Override
    public int compareTo(Student s) {
        return this.sname.compareTo(s.getSname());
    }
 
	//setter/getter
    //toString
 
}

第二步:创建集合,实现排序

//基于数组生成List集合
List<Student> list = Arrays.asList(
    new Student(1002,"jack","男","挖掘机专修",new Date(),88),
    new Student(1005,"rose","女","挖掘机专修",new Date(),55),
    new Student(1006,"lily","男","挖掘机专修",new Date(),59),
    new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
    new Student(1003,"jack","男","挖掘机专修",new Date(),39),
    new Student(1011,"tom","男","挖掘机专修",new Date(),59),
    new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
    new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
    new Student(1012,"admin","男","挖掘机专修",new Date(),99),
    new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
    new Student(1007,"ase","男","挖掘机专修",new Date(),32),
    new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
);

//默认自然排序规则排序(Comparable)
Collections.sort(list);

2.1.2 Comparator:定制排序

第一步:创建用于比较排序的实体类

public class Student{
 
    private int sno;
    private String sname;
    private String sex;
    private String major;
    private Date birth;
    private double score;
 
    //构造器
	//setter/getter
    //toString
 
}

第二步:创建排序比较器对象

1.直接通过匿名内部类实现

List<Student> list = Arrays.asList(
    new Student(1002,"jack","男","挖掘机专修",new Date(),88),
    new Student(1005,"rose","女","挖掘机专修",new Date(),55),
    new Student(1006,"lily","男","挖掘机专修",new Date(),59),
    new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
    new Student(1003,"jack","男","挖掘机专修",new Date(),39),
    new Student(1011,"tom","男","挖掘机专修",new Date(),59),
    new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
    new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
    new Student(1012,"admin","男","挖掘机专修",new Date(),99),
    new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
    new Student(1007,"ase","男","挖掘机专修",new Date(),32),
    new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
);
//排序(使用匿名内部类)
Collections.sort(list, new Comparator<Student>() {
    @Override
    public int compare(Student s1, Student s2) {
        return s1.getSname().compareTo(s2.getSname());
    }
});
 
for (Student s : list) {
    System.out.println(s);
}

2.通过自定义排序类实现Comparator接口

该方式可以实现更好的排序扩展性,需要在上面Student实体类的基础上创建单独排序类:

public class StudentComparator implements Comparator<Student> {
    //用于排序的字段 sno,sname,score,birth
    private String field;
 
    public StudentComparator(String field) {
        this.field = field;
    }
 
    @Override
    public int compare(Student s1, Student s2) {
        switch (field){
            case "sno":
                //按学号排序
                return s1.getSno() - s2.getSno();
            case "sname":
                //按姓名排序
                return s1.getSname().compareTo(s2.getSname());
            case "score":
                //按学分排序
                return (int)(s2.getScore() - s1.getScore());
            case "birth":
                //按生日排序
                return s1.getBirth().compareTo(s2.getBirth());
            default:
                return 0;
        }
    }
 
}

排序实现

public class TestStu {
 
    public static void main(String[] args) {
 
        List<Student> list = Arrays.asList(
                new Student(1002,"jack","男","挖掘机专修",new Date(),88),
                new Student(1005,"rose","女","挖掘机专修",new Date(),55),
                new Student(1006,"lily","男","挖掘机专修",new Date(),59),
                new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
                new Student(1003,"jack","男","挖掘机专修",new Date(),39),
                new Student(1011,"tom","男","挖掘机专修",new Date(),59),
                new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
                new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
                new Student(1012,"admin","男","挖掘机专修",new Date(),99),
                new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
                new Student(1007,"ase","男","挖掘机专修",new Date(),32),
                new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
        );
 
        //使用独立比较器
        Collections.sort(list,new StudentComparator("score"));
 
        for (Student s : list) {
            System.out.println(s);
        }
 
    }
}

2.3 Set和Map集合类型的排序

对于Set和Map类型的集合

  • 可以使用TreeSet和TreeMap进行排序,TreeSet和TreeMap排序也有Camparable:自然排序Comparator:定制排序
  • 可以通过转换的方式,将Set、Map类型的集合转化成List类型的集合,再使用Collections.sort方法对其进行排序。

1.Set

自然排序

public class Student implements Comparable<Student>{
 
    private int sno;
    private String sname;
    private String sex;
    private String major;
    private Date birth;
    private double score;
 
    public Student(int sno, String sname, String sex, String major, Date birth, double score) {
        this.sno = sno;
        this.sname = sname;
        this.sex = sex;
        this.major = major;
        this.birth = birth;
        this.score = score;
    }
 
    /**
     *   自然排序的比较方法
     */
    @Override
    public int compareTo(Student s) {
        return this.sname.compareTo(s.getSname());
    }
 
	//setter/getter
    //toString
 
}
//基于数组生成List集合
List<Student> list = Arrays.asList(
    new Student(1002,"jack","男","挖掘机专修",new Date(),88),
    new Student(1005,"rose","女","挖掘机专修",new Date(),55),
    new Student(1006,"lily","男","挖掘机专修",new Date(),59),
    new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
    new Student(1003,"jack","男","挖掘机专修",new Date(),39),
    new Student(1011,"tom","男","挖掘机专修",new Date(),59),
    new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
    new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
    new Student(1012,"admin","男","挖掘机专修",new Date(),99),
    new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
    new Student(1007,"ase","男","挖掘机专修",new Date(),32),
    new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
);
//将List集合转换为Set,利用TreeSet进行自然排序
Set<Student> set = new TreeSet<>(list);
for (Student s : set) {
    System.out.println(s);
}

定制排序

import java.util.TreeSet;

public class CustomSortingExample {
    public static void main(String[] args) {
        TreeSet<String> names = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

        names.add("John");
        names.add("Alice");
        names.add("Robert");
        names.add("Michael");
        names.add("Alex");

        System.out.println("定制排序结果:");
        for (String name : names) {
            System.out.println(name);
        }
    }
}
定制排序结果:
John
Alex
Alice
Robert
Michael

2.Map

自然排序

public  class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    //getter/setter...

    /**
     * T重写compareTo方法实现按年龄来排序
     */
    @Override
    public int compareTo(Person o) {
        if (this.age > o.getAge()) {
            return 1;
        }
        if (this.age < o.getAge()) {
            return -1;
        }
        return 0;
    }
}

public static void main(String[] args) {
    TreeMap<Person, String> pdata = new TreeMap<Person, String>();
    pdata.put(new Person("张三", 30), "zhangsan");
    pdata.put(new Person("李四", 20), "lisi");
    pdata.put(new Person("王五", 10), "wangwu");
    pdata.put(new Person("小红", 5), "xiaohong");
    // 得到key的值的同时得到key所对应的值
    Set<Person> keys = pdata.keySet();
    for (Person key : keys) {
        System.out.println(key.getAge() + "-" + key.getName());

    }
}

定制排序

import java.util.Comparator;
import java.util.TreeMap;

public class CustomSortingExample {
    public static void main(String[] args) {
        TreeMap<String, Integer> map = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareToIgnoreCase(s2);
            }
        });

        map.put("Apple", 5);
        map.put("banana", 2);
        map.put("Orange", 8);
        map.put("grape", 1);
        map.put("mango", 3);

        System.out.println("定制排序结果:");
        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}
定制排序结果:
Apple: 5
banana: 2
grape: 1
mango: 3
Orange: 8

三.不可变集合

3.1 什么是不可变集合

不可变集合就是不可被修改的集合,集合的元素在创建的时候提供,并且在整个生命周期中不可改变,否则报错。

3.2 不可变集合的作用

  • 如果某个数据不可被修改,把他防御性的拷贝到集合中是个很好的实践。

  • 当集合对象被不可信的库调用时,不可变形式是安全的。

3.3 如何创建不可变集合

在List、Set、Map接口中都存在 of 方法,可以创建一个不可变的集合,这个集合不能增删改。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. Set(集合)里面的元素是无序的,但没有重复的元素 2. 两个实现类HashSet(LinkHashSet)和TreeSet,TreeSet有排序功能(Set set=new TreeSet();set.add(new Integer(8)); set.add(new Integer(4)); set.add(new Integer(7));)输出后的结果是:4 7 8 Eg: package test; import java.util.*; public class Set{ public static void main(String[] args) { //先实例化一个set Set<String> stringSet=new HashSet<String>(); //向set里面添加元素 stringSet.add("123"); stringSet.add("wer"); stringSet.add("345"); //将set里的元素取出 Iterator<String> stringIter=stringSet.iterator(); while(stringIter.hasNext()){ String str=stringIter.next(); System.out.println(str); System.out.println("~~~~~~~~~~~"); } System.out.println("stringSet里面有"+stringSet.size()+"元素"); } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2.List(列表<接口>)以线性方式存储,有序,允许重复主要实现类有LinkList(采用链表数据结构)和ArrayList(代表可大可小的数组) Eg: package test; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; public class Map { public static void main(String[] args) { List list=new ArrayList(); list.add(10); list.add(2); list.add(34); //对list数组进行自然排序 Collections.sort(list); //依次检索输出list的所有对象 // for(int i=0;i<list.size();i++){ // System.out.println(list.get(i)); // } Iterator Iter=list.iterator(); while(Iter.hasNext()){ System.out.println(Iter.next()); } } } 3.Map(映射<集合>)是无序的,是一种把键对象和值对象进行映射的集合,它每一个元素都包含一对键对象和值对象,给出键对象就可以得到值对象,键对象不允许重复,对值没有要求,多个任意键对象可以映射到一个值对象上;如果有相同键对象,最后一次加入的键对象和值对象将会覆盖以前的; Eg: package test; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class NewMap { public static void main(String[] args) { //向map里添加键值对 //如果要对键进行排序Map map=new TreeMap(); Map<Integer,String> map=new TreeMap<Integer,String>(); //Map map=new HashMap(); map.put(1, "yi"); map.put(23, "er"); map.put(12, "san"); map.put(3, "si"); //遍历map Set keys=map.keySet(); Iterator<Integer> stringIter=keys.iterator(); while(stringIter.hasNext()){ int key=stringIter.next(); String value=(String) map.get(key);//根据键key得到value的值 System.out.println(key+"---"+value); } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真滴book理喻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值