05-集合框架——List、Set的实现类


一、List接口的实现类

1.1 ArrayList概述

  • ArrayList 是泛型类
  • 内部采用数组概念
  • Object[]
  • 查找的时间复杂度:
    • 原始:O(n)
    • 通过二分法降低其时间复杂度:O(log2n)
    • 通过get()方法:O(1)

1.2 ArrayList类常用方法

public boolean remove(Object o)删除指定的元素,返回删除是否成功
public E remove(int index)删除指定索引处的元素,返回被删除的元素
public E set(int index,E element)修改指定索引处的元素,返回被修改的元素
public E get(int index)返回指定索引处的元素
public int size()返回集合中的元素的个数
  • 代码示例:
    public static void main(String[] args) {

     ArrayList arrayList = new ArrayList();
     arrayList.add("aaa");
     arrayList.add("bbb");
     arrayList.add("ccc");
     System.out.println(arrayList);
     arrayList.add(1,"eee");
     System.out.println(arrayList);
    
     //删除
     //删除元素 删除指定元素时,如果元素不存在删除失败,返回faLse,如果存在,除成功,返回true
     boolean res1=arrayList.remove("ccc");
     //删除指定索引处的元素 索引M开始 如果指定的索不存在,则抛出ndexoutofBoundsException索引越界异常
     String res2= (String) arrayList.remove(0);
     System.out.println(res1);
     System.out.println(res2);
     //修改
     arrayList.set(0,"abc");
     System.out.println("修改后:"+arrayList);
     //查找
     String res3= (String) arrayList.get(1);
     System.out.println("您要查找的元素为:"+res3);
     //统计集合元素个数
     int res4=arrayList.size();
     System.out.println("集合元素总数:"+res4);
    

    }

1.3 ArrayList练习

1.3.1 练习1—ArrayList存储字符串并遍历

案例需求:
创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合。
实现步骤:
1:创建集合对象;

2:往集合中添加字符串对象;

3:遍历集合,首先要能够获取到集合中的每一个元素,这个通过get(int index)方法实现;

4:遍历集合,其次要能够获取到集合的长度,这个通过size()方法实现;

5:遍历集合的通用格式。

public static void main(String[] args) {
		//创建集合对象
        ArrayList arrayList = new ArrayList();
   	 	//添加字符串对象
        arrayList.add("aaa");
        arrayList.add("bbb");
        arrayList.add("ccc");
        
        arrayList.add(1,"eee");
        System.out.println(arrayList);

        for (int i = 0; i < arrayList.size(); i++) {//获取到集合的长度,通过size()方法实现
            System.out.println(arrayList.get(i));//遍历集合,获取到集合中的每一个元素,通过XX.get(int index)方法实现
        }

在这里插入图片描述

1.3.2 练习2—ArrayList存储学生对象并遍历

案例需求
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

实现步骤:

1:定义学生类;

2:创建集合对象;

3:创建学生对象;

4:添加学生对象到集合中;

5:遍历集合,采用通用遍历格式实现;

//定义学生类
package com.wedu.Dome;

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 +
                '}';
    }
}

//测试类
package com.wedu.Dome;
import java.util.ArrayList;
public static void main(String[] args) {

    	//2:创建集合对象
        ArrayList<Student> students = new ArrayList<>();
   	 	//3:创建学生对象
        Student stu1=new Student("张三",22);
        Student stu2=new Student("李四",33);
        Student stu3=new Student("王五",44);
   		// 4:添加学生对象到集合中
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
    
		//遍历集合的通用格式
        for (int i = 0; i < students.size(); i++) {
            System.out.println(students.get(i));
        }
    }
}

1.4 LinkedList概述

  • LinkedList是泛型类
  • 内部采用的是链表的结构
    • 属于双向链表,即底层是基于双向链表结构来实现
  • 查找的时间复杂度:O(n)
    • 和ArrayList最大的区别就是结构不同,ArrayList是数组结构,LinkedList是链表结构链表的实现数据的时候,如果没有特殊处理的情况下,时间复杂度为O(n)
    • 因此一般用ArrayList来进行查找

1.5 LinkedList集合的特有功能

特有方法:

方法名说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素(删除第一个元素)
public E removeLast()从此列表中删除并返回最后一个元素(删除最后一个元素)

1.6 Vector

  • Vector是泛型类,且比上面两种都要出现得早(JDK1.0就出现了)
  • 与ArrayList大部分全一样,不同的是:性能方面的差异
    • 从方法isEmpty()中可以知道Vector中存在一个同步的概念

二、Set接口及其实现类

2.1 TreeSet集合概述和特点

在这里插入图片描述

  • 不可以存储重复元素
  • 没有索引
  • 底层数据结构:二叉树 红黑树
  • 可以将元素按照规则进行排序
    • TreeSet():根据其元素的自然排序进行排序
    • TreeSet(Comparator comparator) :根据指定的比较器进行排序

2.2 TreeSet集合基本使用

  • 存储Integer类型的整数并遍历
public class TreeSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Integer> ts = new TreeSet<Integer>();

        //添加元素
        ts.add(10);
        ts.add(40);
        ts.add(30);
        ts.add(50);
        ts.add(20);

        ts.add(30);

        //遍历集合
        for(Integer i : ts) {
            System.out.println(i);
        }
    }
}

2.3 TreeSet排序

2.3.1 自然排序Comparable的使用

  • 案例需求

    • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
  • 实现步骤

    1. 使用空参构造创建TreeSet集合
      • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
    2. 自定义的Student类实现Comparable接口
      • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
    3. 重写接口中的compareTo方法
      • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
  • 代码实现

    • 学生类
    public class Student implements Comparable<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 int compareTo(Student o) {
            //按照对象的年龄进行排序
            //主要判断条件: 按照年龄从小到大排序
            int result = this.age - o.age;
            //次要判断条件: 年龄相同时,按照姓名的字母顺序排序
            result = result == 0 ? this.name.compareTo(o.getName()) : result;
            return result;
        }
    }
    
    • 测试类
    public class MyTreeSet2 {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Student> ts = new TreeSet<>();
    	    //创建学生对象
            Student s1 = new Student("zhangsan",28);
            Student s2 = new Student("lisi",27);
            Student s3 = new Student("wangwu",29);
            Student s4 = new Student("zhaoliu",28);
            Student s5 = new Student("qianqi",30);
    		//把学生添加到集合
            ts.add(s1);
            ts.add(s2);
            ts.add(s3);
            ts.add(s4);
            ts.add(s5);
    		//遍历集合
            for (Student student : ts) {
                System.out.println(student);
            }
        }
    }
    

2.3.2 比较器排序Comparator的使用

  • 案例需求

    • 存储老师对象并遍历,创建TreeSet集合使用带参构造方法
    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
  • 实现步骤

    • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
    • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
  • 代码实现

    • 老师类
    public class Teacher {
        private String name;
        private int age;
    
        public Teacher() {
        }
    
        public Teacher(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 "Teacher{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • 测试类
    public class MyTreeSet4 {
        public static void main(String[] args) {
          	//创建集合对象
            TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
                @Override
                public int compare(Teacher o1, Teacher o2) {
                    //o1表示现在要存入的那个元素
                    //o2表示已经存入到集合中的元素
                  
                    //主要条件
                    int result = o1.getAge() - o2.getAge();
                    //次要条件
                    result = result == 0 ? o1.getName().compareTo(o2.getName()) : result;
                    return result;
                }
            });
    		//创建老师对象
            Teacher t1 = new Teacher("zhangsan",23);
            Teacher t2 = new Teacher("lisi",22);
            Teacher t3 = new Teacher("wangwu",24);
            Teacher t4 = new Teacher("zhaoliu",24);
    		//把老师添加到集合
            ts.add(t1);
            ts.add(t2);
            ts.add(t3);
            ts.add(t4);
    		//遍历集合
            for (Teacher teacher : ts) {
                System.out.println(teacher);
            }
        }
    }
    

2.4 HashSet集合概述和特点

  • 底层数据结构是哈希表
  • 存取无序:指的是元素输入和输出的顺序
  • 不可以存储重复元素
  • 没有索引,不能使用普通for循环遍历

2.5 HashSet集合的基本应用

2.5.1 练习—存储字符串并遍历

public class HashSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<String> set = new HashSet<String>();

        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        //不包含重复元素的集合
        set.add("world");

        //遍历
        for(String s : set) {
            System.out.println(s);
        }
    }
}

2.5.2 重复元素判断

  • 为什么要进行重复元素的判断?

    • 一般来说Set的三种实现类是不能存储重复的元素的,那是对于
    • 因为在实体类中,两个一模一样的对象,可能地址值不一样,因此都会被存储到HashSet集合中去
    • 而TreeSet集合存储实体类对象时,因为必须结合Comparable/Comparator接口进行,在这就自动完成了重复元素的筛选,因此在TreeSet集合中不需要再单独进行重复元素的判断
  • 在HashSet中:
    判断重复元素,一定得通过Object类来完成——借助hashCode()方法

  • 进行比较的步骤:
    • 因为每一个对象拥有不同的编码,因此首先hashCode()获取某个对象的编码
    • 再通过equals()方法对其编码传入数据进行对比
import java.util.Objects;

public class Books {
    private String bname;
    private String author;
    private double price;

    public Books() {
    }

    public Books(String bname, String author, double price) {
        this.bname = bname;
        this.author = author;
        this.price = price;
    }

    public String getBname() {
        return bname;
    }

    public void setBname(String bname) {
        this.bname = bname;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Books{" +
                "bname='" + bname + '\'' +
                ", author='" + author + '\'' +
                ", price='" + price + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Books books = (Books) o;
        return Double.compare(books.price, price) == 0 && Objects.equals(bname, books.bname) && Objects.equals(author, books.author);
    }

    @Override
    public int hashCode() {
        return Objects.hash(bname, author, price);
    }
  • 测试类
import java.util.*;

public class TreeSetDemo01 {
    public static void main(String[] args) {
        Set<Books> books = new HashSet<>();//HashSet的无参构造
        Books books1 = new Books("西游记","吴承恩",23.33);
        Books books2 = new Books("水浒传","施耐庵",53.33);
        Books books3 = new Books("红楼梦","曹雪芹",23.33);
        Books books4 = new Books("三国演义","罗贯中",63.66);
        Books books5 = new Books("三国演义","罗贯中",63.66);

        /*System.out.println(books4.equals(books5));
        System.out.println(books1.equals(books3));*/

        books.add(books1);
        books.add(books2);
        books.add(books3);
        books.add(books4);
        books.add(books5);

        for (Books book:books){
            System.out.println(book);
        }
    }
}

2.6 LinkedHashSet概述与特点

  • LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。(有序)
  • LinkedHashSet底层是一个 LinkedHashMap,底层维护了一个数组+双向链表

2.7 三种实现类的异同

  • 存储方式:
    • HashSet:顺序毫无规律?
    • LinkedHashset:怎么存的就怎么取
    • TreeSet:ASCII码排序

  • 三者的实例化都依赖于Map接口(由三者的构造方法可得)
    因此Set接口一般不单独使用,都是结合Map
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值