文章目录
一、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集合使用无参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
-
实现步骤
- 使用空参构造创建TreeSet集合
- 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自定义的Student类实现Comparable接口
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
- 重写接口中的compareTo方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
- 使用空参构造创建TreeSet集合
-
代码实现
- 学生类
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()方法对其编码传入数据进行对比
- 完成重复元素判断的步骤:
- 按照idea提供的自动生成
- 在我的其他篇博客中有快捷方式:常用API-01(Java.lang包)— Object类的equals方法
- 代码示例:
- Books类
- 按照idea提供的自动生成
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