L*_*L

集合框架

集合的概念

什么是集合
  • 概念:对象的容器,实现了对对象常用的操作,类似数组功能。
  • 和数组的区别:
    * 1.数组长度固定,集合长度不固定。
    * 数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置:java.util.*

一、Collection接口

体系集合:

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复。
  • 方法:
    * boolean add(Object obj) //添加一个对象
    * boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中
    * void clear() //清空此集合中的所有对象
    * boolean contains(Object o) //检查此集合中是否包含o对象
    * boolean equals(Object o) //比较此集合是否与指定对象相等
    * boolean isEmpty() //判断此集合是否为空
    * boolean remove(Object o) //在此集合中移除o对象
    * int size() //返回此集合中的元素个数
    * Object[] toArray() //将此集合转换成数组
  • 使用:

二、List接口与实现类

1-1 List接口
* 特点:有序、有下标、元素可以重复。 * 方法: * void add (int index,Object o) //在index位置插入对象 * boolean add(int index,Collection c) //将一个集合中的元素添加到此集合中的index位置 * Object get(int index) //返回集合中指定位置元素 * List subList(int fromIndex,int toIndex) //返回fromIndex和toIndex之间的集合元素
  • 使用 :


1-2 List实现类:
  • ArrayList
    * 数组结构实现 、查询快,增删慢
    * 运行效率快,线程不安全

  • Vector
    * 数组结构实现,线程安全

  • LinkedList
    * 链表结构实现,增删快,查询慢

  • ArrayList源码分析:


  • Vector中的方法:

  • 使用:

  • LinkedList的使用:


三、泛型和工具类

泛型:
  • Java泛型的本质是参数化类型,把类型作为参数传递。

  • 常见形式有:泛型类、泛型接口、泛型方法

  • 语法:
    * <T....>T被称为类型占位符,表示一种引用类型

  • 好处:
    * 提高代码重用性
    * 防止类型转换异常,提高代码安全性。

  • 泛型类的创建与使用

  • 泛型接口的创建与使用


  • 泛型方法:

  • 泛型集合:


四、Set接口与实现类

  • Set接口的使用

  • 实现类

  * HashSet集合的使用:
        * 存储结构:哈希表【数组+链表+红黑树】;
        * 存储过程:
              1. 根据hashcode计算保存的位置,若位置为空,则直接保存;若不为空,进行第二步;
              2. 再执行equals方法,若equals方法为true,则认为是重复;否则生成链表;
        * 改进:
              1. 重写hashcode和equals方法改进写入、删除;
              2. 快速重写hashcode和equals方法:在开发工具中提供的<Generate hashCode() and equals()...>

  * TreeSet集合的使用
        * 存储结构:红黑树;
        * 要求:元素必须要实现Comparable接口,compareTo方法返回值为0,认为是重复元素;

增删改查

由于红黑树的比较特性,需进行如下代码:

public int compareTo(Person o){      //先比较姓名再比较年龄
      int n1 = this.getName().compareTo(o.getName());
      int n2 = this.age.o.getAge();

      return n1 == 0?n2:n1;
}

  * Comparable接口:实现定制比较
//创建集合,并制定比较规则
TreeSet<Person> person = new TreeSet<>(
      new Comparator<person>(){
      public int compareTo(Person o1,Person o2){      //先比较年龄再比较姓名
            int n1 = o1.getAge()-o2.getAge();
            int n2 = o1.getName().compareTo(o2.getName());
            

      return n1 == 0?n2:n1;
}

  * 使用TreeSet集合实现字符串按照长度进行排序
//创建集合,并制定比较规则
TreeSet<String> treeSet = new TreeSet<>(
      new Comparator<String>(){
      public int compareTo(String o1,String o2){      //先比较年龄再比较姓名
            int n1 = o1.length()-o2.length();
            int n2 = o1.compareTo(o2);
            return n1 == 0?n2:n1;
          }
});
//添加数据
TreeSet.add("hello");
TreeSet.add("bello");
TreeSet.add("zello");``
TreeSet.add("lello");
TreeSet.add("aello");
TreeSet.add("xello");

System.out.println(treeSet.toString());

五、Map接口与实现类

1-1 Map接口的特点:
  1. 用于存储任意键值对;
  2. 键:无序、无下标、不允许重复;
  3. 值:无序、无下标、允许重复;
1-2 Map接口的方法:
  * V put(K key,V value)      //将对象存入到集合中,关联键值。key重复则覆盖原值。
  * Object get(Object key)      //根据键获取对应的值
  * Set<K>            //返回所有key
  * Collection<V> values()      //返回包含所有值的Collection集合
  * Set<Map,Entry<K,V>>            //键值匹配的Set集合
1-3 Map接口的使用:

public static void main(String[] args){

      //创建Map集合
      Map<String,String> map = new HashMap<>();
      //1.添加元素
      map.put("cn","中国");
      map.put("uk","英国");
      map.out("usa","美国");
      //2.显示
      System.out.println("元素个数:"+map.size());
      System.out.println(map.toString());

      //3.遍历:
      //3.1 利用keySet()
      System.out.println("---------keySet()------------");
      for(String key : map.keySet()){

            System.out.println(key.toString()+"----"+map.get(key));
      }
      //3.2 使用entrySet()
      System.out.println("---------entrySet()------------");
      for(Map.Entry<String,String> entry : map.entrySet()){

            System.out.println(entry.getKey()+"----"+entry.getValue());
      }

}

2 Map接口的实现类
2-1 HashMap集合

存储结构:哈希表【链表+红黑树+栈】

//添加学生类
public class Student{
      private String name;
      private int stuNo;

      public Student(){

      }

      public Student(String name,int stuNo){
            super();
            this.name = name;
            this.stuNo = stuNo;
      }

      public String getName(){
            return name;
      }
      
      public void setName(String name){
            this.name = name;
      }

      public String getStuNo(){
            return StuNo;
      }
      
      public void setStuNo(String stuNo){
            this.stuNo = stuNo;
      }

      public String toString(){
            return "Student [name="+name+",stuNo="+stuNo+"]";
      }

      
}


//结合Student类使用HashMap集合

public static void main(String[] args){

      //创建集合
      HashMap<Student,String> students = new HashMap<Student,String>();
      //1.添加元素
      Student s1 = new Student("悟空",100);
      Student s2 = new Student("悟能",101);
      Student s3 = new Student("悟净",102);
      students.put(s1,"北京");
      students.put(s2,"南京");
      students.put(s3,"上海");
      //2.显示
      System.out.println("元素个数:"+students.size());
      System.out.println(students.toString());

      //3.遍历
      //3.1 利用keySet()
      System.out.println("---------keySet()------------");
      for(Student key : students.keySet()){

            System.out.println(key.toString()+"----"+students.get(key));
      }
      //3.2 使用entrySet()
      System.out.println("---------entrySet()------------");
      for(Map.Entry<Student,String> entry : students.entrySet()){

            System.out.println(entry.getKey()+"----"+entry.getValue());
      }
      //4.判断
      System.out.println(students.containsKey(s1));
      System.out.println(students.containsValue("上海"));
}

HashMap源码分析总结:
* HashMap刚创建时,table【初始创建的数组】是null,为了节省空间,当添加第一个元素时,table容量调整为16。
* 当元素个数大于阈值【16*0.75=12】时,会进行扩容,每次扩展后为原来大小的2倍,目的是减少调整元素的个数。
* jdk1.8中当每个链表长度大于8并且数组元素个数大于等于64时,会调整红黑树,目的是提高执行效率。
* jdk1.8中当链表长度小于6时调整成链表。
* jdk1.8以前,链表采用头插法,之后使用尾插法。

posted on 2020-12-28 17:26  L*_*L  阅读(46)  评论(0编辑  收藏  举报