概述

  1. 在之前的学习中遇到多个变量,我们是使用数组进行存储
    1. 数组在创建的时候就需要指定长度
    2. 由于数组的长度不可以变,不可以新增,数组在扩容/缩容的时候需要创建一个新的数组
  2. 集合概念和数组类似,也是可以存储多个引用变量
    1. 集合的长度是可以变的
    2. 集合还提供了格式排序,比较等等方法,方便用户对集合的操作
    3. 集合本质上是数组的封装类,本质上最终存储数据还是数组
  3. 根据不同的数据结构,集合可以分为以下几类
    1. List
    2. Set
    3. Map
      1. List:线性有序的集合

集合 - 图1

  1. 2. Set:无序的集合

集合 - 图2

  1. 3. Map:使用key/value的方法进行存储

image.png

List有序集合

  1. List在java是一个接口, 它父类是Collection,它有各种不同的底层实现
    1. ArrayList
    2. LinkedList
    3. Vector
  2. ArrayList的基本使用

    1. 集合的创建,新增,获取 和删除

      1. ArrayList list = new ArrayList();
      2. //给集合中放入对象
      3. list.add(1); //0
      4. list.add("aa");//1
      5. list.add(true);//2
      6. list.add(new Student("小王",15));
      7. //获取数据
      8. Integer i = (Integer) list.get(0);
      9. String aa = (String) list.get(1);
      10. Boolean flag = (Boolean) list.get(2);
      11. Student student = (Student) list.get(3);
      12. list.remove(2);//删除
      13. System.out.println(i);
      14. System.out.println(aa);
      15. System.out.println(flag);
      16. System.out.println(student.toString());
    2. 集合的遍历

      1. //第一种遍历集合的方式
      2. for (int j=0;j<list.size();j++){
      3. System.out.println(list.get(j));
      4. }
      5. //第二种遍历的方式
      6. System.out.println("第一个遍历的方式:");
      7. //类型 一个对象的变量 : 集合的遍历
      8. for (Object obj :list) {
      9. System.out.println(obj);
      10. }
      11. //第三种方式lambda表达式
      12. list.forEach(obj->{
      13. System.out.println(obj);
      14. });

      泛型

  3. List有三种中实现,都是继承的List接口只是在实现上不同,在使用上是一摸一样的

    1. LinkedList是通过链表,删除和新增的速度快查询慢
    2. ArrayList是查询快,删除和新增慢
    3. Vector都慢,但是线程安全
  4. 所以在使用的时候,都会直接使用List指向三种不同类型的集合

    1. List list = new ArrayList();
    2. List linkedList = new LinkedList();
  5. 在list的add 和 get方法,是不需要设置类型的

    1. 在添加虽然可以放入不同的数据类型
    2. 但是在获取结果的时候需要强制类型转换,就会影响程序的速度
    3. 可以通过泛型解决这个问题
  6. 泛型指的是可以将集合中的数据定义成指定的类型,在获取结果的时候不需要强制类型转换

    1. List<Integer> list = new ArrayList();
    2. //List linkedList = new LinkedList();
    3. list.add(1);//只能存放Integer类型
    4. //list.add("a");
    5. Integer i = list.get(0);//获取数据的不需要进行类型转换
  7. 泛型的定义

    1. 一个泛型参数定义

      1. public class MyArrayListImpl<T> {
      2. public void add(T obj){
      3. }
      4. public T get(int i){
      5. return null;
      6. }
      7. }
    2. 多个泛型参数的定义

      1. public class MyConvert<S,D> {
      2. public D to(S a){
      3. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
      4. return (D) simpleDateFormat.format(a);
      5. }
      6. }

      Collections工具类

  8. reverse实现集合的反转

  9. shuffle:随机重置
  10. sort:可以进行排序

    1. 默认情况下是直接使用升序
    2. 如果需要使用降序,请重写Comparator接口
      1. Collections.sort(list, new Comparator<Integer>() {
      2. //实现比较的规则
      3. @Override
      4. public int compare(Integer o1, Integer o2) {
      5. if(o1>o2){
      6. return -1;
      7. }else if(o1<o2){
      8. return 1;
      9. }
      10. return 0;
      11. }
      12. });
  11. binarySearch:使用二分查询,查找对应的值的下标

    1. 必须要是升序的排序
    2. 查询的是关键字

      1. int result = Collections.binarySearch(list, new Student("学生" + 6, 13), (o1, o2) -> {
      2. if(o1.getAge()>o2.getAge()){
      3. return 1;
      4. }else if(o1.getAge()<o2.getAge()){
      5. return -1;
      6. }
      7. //两个值相同
      8. return 0;
      9. });
      10. System.out.println("查询的结果是:"+result);

      Set无序集合

  12. 将一组对象,直接放入到集合中,默认情况下没有顺序概念,不能插入相同的元素

  13. 一般添加元素

    1. //创建对象
    2. Book b1 = new Book("天龙八部","金庸",98);
    3. Book b2 = new Book("神雕侠侣","金庸",78);
    4. Book b3 = new Book("背影","朱自清",18);
    5. //创建集合
    6. Set<Book> set = new HashSet<>();
    7. //将对象放入到集合中
    8. set.add(b1);
    9. set.add(b2);
    10. set.add(b3);
  14. 遍历集合

    1. //遍历集合查询
    2. //增强foreach
    3. /*
    4. for (Book book :set) {
    5. System.out.println(book.toString());
    6. }*/
    7. //使用lambda表达式
    8. /*
    9. set.forEach(book -> {
    10. System.out.println(book.toString());
    11. });*/
    12. //使用迭代器
    13. Iterator<Book> iterable = set.iterator();
    14. //循环迭代
    15. while(iterable.hasNext()){
    16. Book book = iterable.next();
    17. System.out.println(book.toString());
    18. }
  15. 三种实现

    1. HashSet:底层直接使用HashMap进行实现的,
      1. 在长度超过一定数量的时候,会进行数据重排
      2. 主要是通过hashCode定义元素的插入位置
      3. 在判断两个元素是否一致的时候,需要重写hashCode和equals两个方法
    2. LinkedHashSet:由于底层主要是通过链表实现的,没有扩容的问题,
      1. 会保证插入的顺序是不变的
    3. TreeSet:底层是通过tree实现的
      1. Collections的sort只对list有效,如果要使用排序则要使用TreeSet
      2. 插入的对象需要实现Comparable接口才行
      3. 在重写Comparable接口的时候,如果返回的结果是0,那么元素就不会被插入了
  16. equals和hashcode的区别

    1. equals主要是用于判断两个对象的值是否相同
    2. hashcode是hash集合的位置,在hash集合中判断两个元素是否一致主要是通过hashcode进行判断

      Map键值集合

  17. 通过key将对应的值放入到集合中,在集合中主要是通过key定义元素的位置

    1. Map map = new HashMap();
    2. //放入值
    3. map.put(1,"小明");
    4. //获取值
    5. Object result = map.get(1);
    6. System.out.println("result="+result);
    7. map.put("a","小明");
    8. map.put("a","小黑");
    9. Object rs = map.get("a");
    10. System.out.println("a的值:"+rs);
  18. HashMap存储的最小的单位是一个Entry(其中包括了key和Value)

    1. public static void main(String[] args) {
    2. Map<Integer, Student> map = new HashMap<>();
    3. for(int i=0;i<5;i++){
    4. map.put(i,new Student("学生"+i,1+i));
    5. }
    6. //第一种,通过EntrySet遍历
    7. //获取map中所有的entry
    8. Set<Map.Entry<Integer,Student>> entrySet = map.entrySet();
    9. //遍历存储了所有的entry的Set
    10. for (Map.Entry<Integer, Student> entry :map.entrySet()) {
    11. //获取Entry的key值
    12. Integer key = entry.getKey();
    13. //获取Entry具体存储的值
    14. Student s = entry.getValue();
    15. System.out.println(key+":"+s.getName());
    16. }
    17. //第二种通过遍历keySet获取值
    18. for (Integer key : map.keySet()) {
    19. //通过key获取值
    20. Student value = map.get(key);
    21. System.out.println(key+":"+value.getName());
    22. }
    23. //第三种使用lambda表达式
    24. map.forEach((key,value)->{
    25. System.out.println(key+":"+value.getName());
    26. });
    27. }
  19. Map的实现

    1. HashMap:基本实现,使用key-value形式对数据进行存储,并且是在Hashtable的基础上进行了优化,速度很快,但是线程不安全,需要使用ConcurrentHashMap保证线程的安全
    2. TreeMap:可以对key值进行排序

      1. 所以key的类需要实现Comparable ```java public class MyKey implements Comparable{ String key;

      public MyKey(String key) { this.key = key; }

      public String getKey() { return key; }

      public void setKey(String key) { this.key = key; }

      @Override public int compareTo(MyKey o) { Integer keyValue = Integer.parseInt(o.getKey());

      return Integer.parseInt(this.key)-keyValue; }

      @Override public String toString() { return “MyKey{“ +

      1. "key='" + key + '\'' +
      2. '}';

      } } ```

    3. Properties也是map的实现,可以直接从文本文件中通过key读取其相关的值

      1. 创建一个properties文件,以key=value的形式存储数据

        1. name=小明
        2. password=123
      2. 通过代码加载文件,读取数据

        1. Properties ps = new Properties();
        2. //加载properties的文件
        3. ps.load(TestMap004.class.getResourceAsStream("info.properties"));
        4. //通过key将properties文件中的值进行获取
        5. String name = ps.getProperty("name");
        6. String pwd = ps.getProperty("password");
        7. System.out.println(name+":"+pwd);