一、集合体系结构
单列集合:Collection
双列集合:Map
二、单列集合
List系列集合:添加的元素是有序、可重复、有索引
有序指的是存和取的顺序是一致的,和之前排序的从小到大是没有任何关系的
Set系列集合:添加的元素是无序、不重复、无索引
2.1、Collection
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数/集合的长度 |
代码实例
2.1.1、添加元素
public class CollectionTest {
public static void main(String[] args) {
/*
Collection是一个接口,我们不能直接创建他的对象
所以,现在我们为了学习Collection的方法时,只能创建他实现类的对象。
实现类:ArrayList 作为一个例子
目的:为了学习Collection接口里面的方法
*/
//自己练习的时候按照自己的方式创建就行
Collection<String> collection =new ArrayList<>();
//添加元素
//细节一:如果我们要往List系列集合中添加元素,那么方法永远返回true,因为List系列的是允许元素重复的。
//细节二:如果要往Set系列集合中添加元素,如果当前要添加元素不存在,方法返回true,表示添加成功。
// 如果当前要添加元素已经存在,方法返回false,表示添加失败。
// 因为Set系列的集合不允许元素重复。
collection.add("张三");
collection.add("李四");
collection.add("王五");
System.out.println(collection);
}
}
运行结果:
2.1.2、清空集合
public class CollectionTest {
public static void main(String[] args) {
Collection<String> collection =new ArrayList<>();
collection.add("张三");
collection.add("李四");
collection.add("王五");
System.out.println(collection);
//清空集合
collection.clear();
System.out.println(collection);
}
}
运行结果:
2.1.3、删除元素
package cn.ysy.collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest {
public static void main(String[] args) {
Collection<String> collection =new ArrayList<>();
collection.add("张三");
collection.add("李四");
collection.add("王五");
System.out.println(collection);
//删除
//细节一:因为Collection里面定义的是共性的方法(要同时兼顾到List和Set),所以此时不能通过索引进行删除,只能通过元素的对象进行删除。
//细节二:方法会有一个布尔类型的返回值,删除成功返回ture,删除失败返回false。
System.out.println(collection.remove("张三"));
System.out.println(collection);
}
}
运行结果:
2.1.4、判断元素是否存在
public class CollectionTest {
public static void main(String[] args) {
Collection<String> collection =new ArrayList<>();
collection.add("张三");
collection.add("李四");
collection.add("王五");
System.out.println(collection);
//判断元素是否包含
//细节:底层是依赖equals方法进行判断是否存在的。
//所以,如果集合中存储的是自定义对象,也想用过contains方法来判断是否包含,那么在javabean类中,一定要重写equals方法。
//在String中,==比较引用地址是否相同,equals()比较字符串的内容是否相同
System.out.println(collection.contains("张三"));
}
}
运行结果:
引申:如果是自定义对象,又该怎么比较呐?
创建一个User实体类:
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "User{name = " + name + ", age = " + age + "}";
}
//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age && Objects.equals(name, user.name);
}
}
再写一个Collection测试类:
public class CollectionTest02 {
public static void main(String[] args) {
//1.创建集合对象
Collection<User> collection =new ArrayList<>();
//2.创建三个用户对象
User user1 = new User("张三", 20);
User user2 = new User("李四", 21);
User user3 = new User("王五", 22);
//3.将User对象添加到集合中
collection.add(user1);
collection.add(user2);
collection.add(user3);
//4.判断集合中某一个use对象是否包含
User user4 = new User("张三", 20);
//如果同姓名和年龄,则认为是同一个用户,结果应该是true,但是真实运行结果却是false
//因为contains方法底层调用的是equals方法
//如果存的是自定义对象,没有重写equals,那么默认使用Object类中的equals方法进行判断
//而Object类中的equals方法比较的是地址值
//需求:如果同姓名和年龄,则认为是同一个用户,结果应该是true
//所以,需要在自定义的javabean类中,重写equals方法就可以了
System.out.println(collection.contains(user4));
}
}
没重写equals方法的话,打印结果是false,重写之后,打印结果就是true了
2.1.5、判断集合是否为空和获取集合长度
public class CollectionTest {
public static void main(String[] args) {
Collection<String> collection =new ArrayList<>();
collection.add("张三");
collection.add("李四");
collection.add("王五");
System.out.println(collection);
//判断集合是否为空
System.out.println(collection.isEmpty());
//获取集合的大小
System.out.println(collection.size());
}
}
运行结果:
2.1.6、Collection的遍历方式
迭代器遍历
增强for遍历
lambda表达式
之所以不用普通的for遍历,因为set集合中没有索引,所以不能通过普通for进行遍历
2.1.6.1、迭代器遍历
迭代器在java中的类是Iterator,迭代器是集合专用的遍历方式。
迭代器遍历集合的时候是不依赖索引的
Collection集合获取迭代器
Iterator<E> iterator() 返回迭代器对象,默认指向当前集合的0索引
Iterator中的常用方法boolean hasNext() 判断当前位置是否有元素,有元素返回tru额,反之false
E next() 获取当前位置的元素,并将迭代器对象移向下一个位置
public class CollectionIteratorTest {
public static void main(String[] args) {
Collection<String> collection =new ArrayList<>();
//添加元素
collection.add("a");
collection.add("b");
collection.add("c");
collection.add("d");
//创建迭代器
Iterator<String> iterator = collection.iterator();
//利用迭代器遍历集合
while(iterator.hasNext()){
String result = iterator.next();
System.out.println(result);
}
}
}
细节注意点:
1、当遍历完成时,还强行调用next()方法取获取元素时,就会报错NoSuchElementException
2、迭代器遍历完毕,指针不会复位
3、循环中智能用一次next方法
4、迭代器遍历时,不能用集合的方法进行增加或者删除
2.1.6.2、增强for遍历
- 增强for的底层就是迭代器,为了简化迭代器的代码书写的
- 它是JDK5之后出现的,其内部原理就是一个Iterator迭代器
- 所有的单列集合和数组才能用增强for进行遍历
格式:
for (元素的数据类型 变量名 : 数组或者集合){
}
idea快捷生成 集合名.for
增强for的细节:修改增强for中的变量,不会改变集合中原本的数据
for(String s : list){
System.out.println(s);
}
2.1.6.3、Lambda表达式遍历
得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
collection.forEach(s -> System.out.println(s));
2.2、List
- Collection的方法List都继承了
- List集合因为有索引,所以多了很多索引操作的方
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
细节:利用remve删除元素时,如果类型是整数,那么此时删除的是1这个元素,还是1索引上的元素?为什么?
因为在调用方法的时候,如果方法出现了重载现象,有限调用:实参跟形参类型一致的那个方法。
比如:list.remove(1) 删除的就是1索引位置的元素
如果要删除整数1,则可以手动装箱,将基本数据类型的1,变成Integer类型
Integer i = Integer.valueOf(1);
list.remove(i);// 此时删除的就是元素1了
2.3.1、List集合的遍历方式
2.3.1.1、迭代器
//迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
2.3.1.2、列表迭代器
//列表迭代器遍历
//获取一个列表迭代器的对象,里面的指针默认也是指向0索引的
//额外添加了一个方法;在遍历的过程中,可以添加元素
ListIterator<String> it = list.listIterator();
while (it.hasNext()){
String next = it.next();
if ("2".equals(next)){
it.add("qqqq");
}
}
System.out.println(list);
不能使用集合的方法取添加,比如list.add()会报错并发修改异常,所以要用迭代器本身的方法进行添加
结果:
2.3.1.3、增强for
//增强for
for (String s : list) {
System.out.println(s);
}
2.3.1.4、Lambda表达式
//Lambda表达式
list.forEach(s -> System.out.println(s));
2.3.1.5、普通for循环
//普通for循环遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
2.3.2、五种遍历方式的对比
2.3、数据结构
2.3.1、栈
栈的特点 :先进后出
数据进入栈模型的过程称为:压/进栈数据离开栈模型的过程称为:弹/出栈
2.3.2、队列
队列特点:先进先出
数据从后端进入队列模型的过程称为:入队列数据从前端离开队列模型的过程称为:出队列
2.3.3、数组
数组是一种查询快,增删慢的模型
查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)删除效率低:要将原始数据删除,同时后面每个数据前移
添加效率低:添加位置后的每个数据后移,再添加元素
2.3.4、链表
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。
链表查询慢,无论查询哪个数据都要从头开始找
链表增删相对快
2.3.5、树
二叉查找树:
添加节点规则:
遍历方式:
前序遍历:
中序遍历:
后序遍历:
层序遍历:
平衡二叉树:
红黑树:
2.4、ArrayList
底层原理:
源码分析
情况一:初始长度为0
情况二:当集合长度满时
2.5、LinkedList
源码分析
2.6、迭代器源码
2.7、泛型
泛型的好处: