前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下
(1)长度在声明时必须制定,而且一旦制定,不能修改
(2)保存的必须为同一类元素
(3)使用数组进行增加/删除元素代码比较复杂
例如:
(1)可以动态保存任意多个对象
(2)提供了一系列方便操作对象的方法:add、remove、set、get
(3)集合添加/删除元素代码变得简洁了
(1)collection实现子类可以存放多个元素,每个元素可以是Object
(2)有些Collection的实现类可以存放重复的元素,有些则不可以
(3)有些Collection的实现类元素是有序的,即顺序与存进去的顺序保持一致,比如List接口的实现类,有些则是无序的,例如Set接口的实现类
(4)Collection接口没有直接实现子类,是通过List及Set子接口来实现的
package com.francis.collenction_;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Francis
* @create 2021-09-19 18:14
*/
public class CollectionMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection collection= new ArrayList();
List list = new ArrayList();
// add:添加单个元素
list.add("jack");
list.add(10);//list.add(new Integer(10))
list.add(true);
System.out.println("list=" + list);
// remove:删除指定元素
//list.remove(0);//删除第一个元素
list.remove(true);//指定删除某个元素
//如果要删除整型数据,可以采用一下方法
list.remove(new Integer(10));
System.out.println("list=" + list);
// contains:查找元素是否存在
System.out.println(list.contains("jack"));//T
// size:获取元素个数
System.out.println(list.size());//2
// isEmpty:判断是否为空
System.out.println(list.isEmpty());//F
// clear:清空
list.clear();
System.out.println("list=" + list);
// addAll:添加多个元素
ArrayList list2 = new ArrayList();
list2.add("红楼梦");
list2.add("西游记");
list2.add("三国演义");
list.addAll(list2);
System.out.println("list=" + list);
// containsAll:查找多个元素是否都存在,与顺序无关
List list3 = new ArrayList();
list3.add("三国演义");
list3.add("红楼梦");
System.out.println(list.containsAll(list2));//T
System.out.println(list.containsAll(list3));//T
// removeAll:删除多个元素
list.add("聊斋");
list.removeAll(list2);
System.out.println("list=" + list);//[聊斋]
}
}
(1)所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
(2)Iterator称为迭代器对象,主要用于遍历Collection集合中的元素
(3)Iterator进用于遍历集合,本身不存放对象
(4)Iterator结构图
注意:在调用it.next()之前,必须要先调用it.hasNext()进行监测,若不调用,且下一条记录无效,则会抛出NoSuchElementException异常
package com.francis.collenction_;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Francis
* @create 2021-09-19 21:30
*/
public class CollectionIterator {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
//System.out.println("col=" + col);
//现在希望能够遍历 col 集合
//1. 先得到 col 对应的 迭代器
Iterator iterator = col.iterator();
//2. 使用 while 循环遍历
// while (iterator.hasNext()) {//判断是否还有数据
// //返回下一个元素,类型是 Object
// Object obj = iterator.next();
// System.out.println("obj=" + obj);
// }
//教大家一个快捷键,快速生成 while => itit
//显示所有的快捷键的的快捷键 ctrl + j
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//3. 当退出 while 循环后 , 这时 iterator 迭代器,指向最后的元素
// iterator.next();//NoSuchElementException
//4. 如果希望再次遍历,需要重置我们的迭代器
iterator = col.iterator();
System.out.println("===第二次遍历===");
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
}
}
class Book {
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
增强for循环可以代替iterator迭代器,其本质就是简化版的iterator,只能用来遍历集合或数组
package com.francis.collenction_;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author Francis
* @create 2021-09-19 21:47
*/
public class CollectionFor {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book1("三国演义", "罗贯中", 10.1));
col.add(new Book1("小李飞刀", "古龙", 5.1));
col.add(new Book1("红楼梦", "曹雪芹", 34.6));
for (Object obj : col) {
System.out.println(obj);
}
}
}
class Book1 {
private String name;
private String author;
private double price;
public Book1(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
List接口是Collection接口的子接口,其有以下特点:
(1)List集合类中元素有序(即添加顺序与去除顺序一直)且可重复
(2)List集合中的每个元素都有其对应的顺序索引,即支持索引
(3)Lis容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号取出容器中的元素
(4)实现List接口的实现类有很多,常用的就有Vector、ArrayList、LinkedList
package com.francis.collenction_.list_;
import java.util.ArrayList;
import java.util.List;
/**
* @author Francis
* @create 2021-09-20 8:11
*/
public class List_ {
@SuppressWarnings({"all"})
public static void main(String[] args) {
//1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复 [案例]
List list = new ArrayList();
list.add("jack");
list.add("tom");
list.add("mary");
list.add("hsp");
list.add("tom");
System.out.println("list=" + list);
//2. List 集合中的每个元素都有其对应的顺序索引,即支持索引
// 索引是从 0 开始的
System.out.println(list.get(3));//hsp
}
}
package com.francis.collenction_.list_;
import java.util.ArrayList;
import java.util.List;
/**
* @author Francis
* @create 2021-09-20 8:16
*/
public class ListMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三丰");
list.add("贾宝玉");
System.out.println("list=" + list);
// void add(int index, Object ele):在 index 位置插入 ele 元素
//在 index = 1 的位置插入一个对象
list.add(1, "宋江");
System.out.println("list=" + list);
// boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来
List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(list2);
System.out.println("插入集合的默认格式");
System.out.println("list=" + list);
list.addAll(1, list2);
System.out.println("list=" + list);
// Object get(int index):获取指定 index 位置的元素
//说过
// int indexOf(Object obj):返回 obj 在集合中首次出现的位置
System.out.println(list.indexOf("tom"));//2
System.out.println(list.lastIndexOf("tom"));
// int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置,如果不存在,返回-1
list.add("宋江");
System.out.println("list=" + list);
System.out.println(list.lastIndexOf("宋江"));
// Object remove(int index):移除指定 index 位置的元素,并返回此元素
list.remove(0);
//移除第一个obj
list.remove("宋江");
System.out.println("移除宋江后list=" + list);
// Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换.
list.set(1, "玛丽");
System.out.println("list=" + list);
// List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndex
List returnlist = list.subList(0, 2);
System.out.println("returnlist=" + returnlist);
}
}
(1)迭代器Iterator
(2)增强for循环
(3)普通for循环
package com.francis.collenction_.list_;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* @author Francis
* @create 2021-09-20 9:20
*/
@SuppressWarnings({"all"})
public class ListFor {
public static void main(String[] args) {
//List 接口的实现子类 Vector LinkedList
//List list = new ArrayList();
//List list = new Vector();
List list = new LinkedList();
list.add("jack");
list.add("tom");
list.add("鱼香肉丝");
list.add("北京烤鸭子");
//遍历
//1. 迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
System.out.println("=====增强 for=====");
//2. 增强 for
for (Object o : list) {
System.out.println("o=" + o);
}
System.out.println("=====普通 for====");
//3. 使用普通 for
for (int i = 0; i < list.size(); i++) {
System.out.println("对象=" + list.get(i));
}
}
}
(1)ArrayList可以放入所有元素,包括null,并且可以有多个
(2)ArrayList是由数组来实现数据存储的
(3)ArrayList基本等同于Vector,除了ArrayList是线程不安全的,但执行效率高,在多线程情况下,不建议使用ArrayList
(1)与ArrayList一样,Vector底层也是一个对象数组
(2)Vector是线程同步的,即是线程安全的,Vector类的操作方法都带有synchronize修饰
(3)在开发中,需要线程安全的场景时,考虑使用Vector
ArrayList的无参构造器只是初始化了一个空数组,数组的长度是在第一次调用add方法时才确定为10的,而Vector的无参构造器直接将数组的长度初始化为10。
(1)LinkedList 底层实现了双向链表和双端队列特点
(2)LinkedList 可以添加任意元素,包括重复元素和null
(3)LinkedList 是线程不安全的,没有实现同步
(1)LinkedList 底层维护了一个双向链表
(2)LinkedList 中维护了两个属性first和last分别指向首节点和尾结点
(3)每个节点(Node对象),prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个,最终实现双向链表
(4)所以LinkedList 的元素的添加、删除不是通过数组来完成的,相对说效率较高
如何选择使用ArrayList还是LinkedList
(1)如果程序中改查较多,选择ArrayList
(2)如果增删较多,选择LinkedList
(3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下回选择ArrayList
(4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是LinkedList,而另一个模块使用的是ArrayList