集合
集合的概述
我们为什么要用集合:
我们所学的Java,是一门面向对象的语言,面向对象是基于描述现实事物而存在的,一旦我们所用的数据多了起来,我们就必须要对这些对象进行存储,我们存储之后,就不能是定义一个遍历了,我们需要一个类似于数组这样的容器来进行存储。
到现在为止,已经记录了数组、StringBuffer。但都有一些弊端,StringBuffer的结果是一个字符串,我们在显示业务中,大多数都是以对象的形式进行存储,这样的话,StringBuffer就不满足了,只能选择数组,而数组存储的是对象引用,这样的对象称之为对象数组。
对象数组也不能满足我们一些业务需求的变化,因为数组的长度唯一,这时,为了适应变化,Java提供了一个技术来解决这样的问题,也就是:集合。
数组和集合的区别
长度:
数组的长度唯一
集合的长度不唯一、可变、弹性
内容不同:
数组存储的元素类型是一致的、统一的
集合可以存储不同类型的元素
元素的数据类型:
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用数据类型
有关集合的一个小图
我们可以看到Collection、List都是接口,下面的Arraylist、LinkedList才是实现类
Connection集合
是所有集合的顶层接口,存在着一些可以重复元素的集合,一些不可以重复元素的集合,有些有序,有些无须
添加功能
boolean add(E e) 确保此集合包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合(可选操作)
List list = new List();
Collection c = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
System.out.println(c);//[hello, world]
boolean addAll(Collection<? extends E> c)
Collection c = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
System.out.println(c);//[hello, world]
Collection c1 = new ArrayList();
c1.addAll(c);
System.out.println(c1);//[hello, world]
删除功能
void clear() 从此集合中删除所有元素(可选操作)。
boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
boolean removeAll(Collection<?> c) 删除指定集合中包含的所有此集合的元素(可选操作)。
boolean remove(Object o)
Collection c = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
System.out.println(c);//[hello, world]
c.remove("hello");
System.out.println(c);//[world]
//只删除了hello
boolean removeAll(Collection<?> c)
只删除包含该集合的元素:
c中只删除了c1中和它重复的元素
public static void main(String[] args) {
Collection c = new ArrayList();
Collection c1 = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
c.add("java");
System.out.println(c);//[hello, world]
System.out.println("**********删除之后*************");
c1.add("hello");
c.removeAll(c1);
System.out.println(c);
}
}
//[hello, world, java]
//**********删除之后*************
//[world, java]
判断功能
boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。
boolean containsAll(Collection<?> c) 如果此集合包含指定 集合中的所有元素,则返回true。
boolean isEmpty() 如果此集合不包含元素,则返回 true 。
boolean contains(Object o)
Collection c = new ArrayList();
Collection c1 = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
c.add("java");
System.out.println(c);//[hello, world]
System.out.println(c.contains("hello"));//true
boolean containsAll
c中包含了c1
Collection c = new ArrayList();
Collection c1 = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
c.add("java");
System.out.println(c);//[hello, world]
c1.add("hello");
System.out.println(c.containsAll(c1));//true
boolean isEmpty()
Collection c = new ArrayList();
Collection c1 = new ArrayList();
//boolean add(E e) 确保此集合包含指定的元素(可选操作)
c.add("hello");
c.add("world");
c.add("java");
System.out.println(c);//[hello, world]
System.out.println(c.isEmpty());//false
c.clear();
System.out.println(c.isEmpty());//true
集合的遍历
按照顺序一个一个取出元素,Object[] toArray()把集合转化成数组,可以实现集合的遍历
注意:遍历集合中的元素,里面的元素获取到之后需要向下转型
Collection c = new ArrayList<>();
c.add("hello");
c.add("world");
c.add("java");
//将集合转换成数组
Object[] objects = c.toArray();
for(int i=0;i<objects.length;i++){
//输出的内容是String类型,但是上面的objects是Object类型,需要向下转型
String objects1 = (String) objects[i];
System.out.println(objects1);
}
}
}
//hello
//world
//java
有关iterator迭代器
Iterator iterator() 迭代器,集合的专用遍历方式
两个方法:
boolean hasNext() 如果迭代具有更多的元素,就返回true
E next() 返回迭代中的下一个元素,获取元素
NoSuchElementException - 如果迭代没有更多的元素,报这个错
迭代器遍历:
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator iterator = c.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
String next1 = (String) next;
System.out.println(next1);
}
}
}
//hello
//world
//java
使用迭代器遍历集合中的元素
Collection c = new ArrayList();
Student1 s1 = new Student1("张三", 21);
Student1 s2 = new Student1("李四", 22);
c.add(s1);
c.add(s2);
Iterator iterator = c.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
Student1 next1 = (Student1) next;
System.out.println(next1.getName()+"---"+next1.getAge());
}
}
}
//张三---21
//李四---22
使用迭代器遍历字符串中的元素
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator iterator = c.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
String next1 = (String) next;
System.out.println(next1);
}
}
}
//hello
//world
//java
有关使用迭代器的一个小思考
我们可以看到,迭代器是遍历集合的一种方式,那为什么我们不把迭代器直接定义为一个类呢,这样直接用的话不是方便很多吗,为什么迭代器是一个接口呢。
迭代器源码
我们看到这里面,Collection和List一个继承于Iterable,一个继承于Collection,里面都有一个Iterator()方法,该方法时实现了Iterator接口,Iterator接口中有迭代器的hasNext()和next()方法,最后时Arraylist类中的Itr实现了迭代器的两个方法
public interface Iterator{
boolean hasNext();
Object next();
}
public interface Iterable{
Iterator iterator();
}
public interface Collection extends Iterable{
Iterator<T> iterator();
}
public interface List extends Collection{
Iterator iterator();
}
public class ArrayList implements List{
public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator{
public boolean hasNext(){}
public Object next(){}
}
}
List集合
- 特点:有序集合(存储和取出的顺序一致),可以有重复元素
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
String next1 = (String) next;
System.out.println(next1);
}
}
}
//hello
//world
//java
存储自定义对象并遍历
List list = new ArrayList();
Student1 s1 = new Student1("张三", 21);
Student1 s2 = new Student1("李四", 22);
list.add(s1);
list.add(s2);
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
Student1 next1 = (Student1) next;
System.out.println(next1.getName()+"---"+next1.getAge());
}
}
}
//张三---21
//李四---22
List集合添加功能
void add(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);//[hello, world, java]
list.add(1,"hadoop");
System.out.println(list);//[hello, hadoop, world, java]
List集合获取功能
E get(int index) 返回此列表中指定位置的元素。
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);//[hello, world, java]
list.add(1,"hadoop");
System.out.println(list);//[hello, hadoop, world, java]
System.out.println(list.get(1));//hadoop
删除功能
E remove(int index) 删除该列表中指定位置的元素(可选操作)。
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);//[hello, world, java]
list.add(1,"hadoop");
System.out.println(list);//[hello, hadoop, world, java]
System.out.println(list.get(1));//hadoop
System.out.println(list.remove(1));//hadoop
修改功能
E set(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);//[hello, world, java]
list.add(1,"hadoop");
System.out.println(list);//[hello, hadoop, world, java]
System.out.println(list.get(1));//hadoop
System.out.println(list.remove(1));//hadoop
System.out.println(list);//[hello,world,java]
list.set(1,"hadoop");
System.out.println(list);//[hello,hadoop,java]
列表迭代器
ListIterator listIterator() 返回列表中的列表迭代器(按适当的顺序)。
是List特有的迭代器,该迭代器继承了Iterator,所以也有hasNext和next方法
List是继承自Collection,有父类的功能,也有自己的特有功能:
E previous() 返回列表中的上一个元素,并向后移动光标位置。
boolean hasPrevious() 返回 true如果遍历反向列表,列表迭代器有多个元素。
注意:如果想要逆序遍历,必须先正序遍历一次,才能逆序遍历,一般情况下无意义,一般不使用
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
String next1 = (String) next;
System.out.println(next1);
}
System.out.println("*********************");
while(listIterator.hasPrevious()){
Object previous = listIterator.previous();
String previous1 = (String) previous;
System.out.println(previous1);
}
}
}
//hello
//world
//java
//*********************
//java
//world
//hello
特有功能:get、size
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
System.out.println("********************");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println("********************");
for(int i=0;i<list.size();i++){
Object o = list.get(i);
String o1 = (String) o;
System.out.println(o1);
}
并发修改异常
我们现在有一个问题,我们打算判断集合中有没有“world”这个元素,如果有的话,我们就添加一个"hadoop"
ConcurrentModificationException:并发修改异常。当方法里面检测到对象的并发修改的时候但是,这里不允许修改时,就会抛出这种异常
为什么会出现这种异常呢?
迭代器是依赖于集合存在的,在判断成功之后,集合中添加了新的元素,但是迭代器不知道,所以就报错了,这就是并发修改异常。
也就是说,迭代器遍历元素的时候,集合是不能修改元素的
怎么解决呢
1、迭代器遍历元素,迭代器修改元素
添加的元素紧跟在刚刚迭代到的元素后面
2、集合遍历元素,集合修改元素
添加的元素在最后一个
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
String next1 = (String) next;
if("world".equals(next1)){
list.add("hadoop");
}
}
//这就会出现并发修改异常ConcurrentModificationException
或者这种情况也会出现并发修改异常(正确的代码里面,Iterator it = c.iterator() 应该放到c.add()后面,放到前面的话,就意味着先有了迭代器,之后再去修改数组,也会出现并发修改异常,也就是迭代器和数组不是同时被改变)
public static void main(String[] args) {
Collection c = new ArrayList();
Student1 s1 = new Student1("张三", 21);
Student1 s2 = new Student1("李四", 22);
Student1 s3 = new Student1("王五", 23);
Student1 s4 = new Student1("赵六", 24);
Student1 s5 = new Student1("张三", 28);
Iterator it = c.iterator();
//将Student类对象添加进集合中
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
while (it.hasNext()) {
Object next = it.next();
Student1 s = (Student1) next;
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
并发修改异常的解决办法
使用集合遍历元素,集合修改元素
使用迭代器遍历元素,迭代器修改元素
//迭代器遍历元素,迭代器修改元素
List list = new ArrayList();
list.add("hello");
list.add("world");
ListIterator listIterator = list.listIterator();
for(int i=0;i<list.size();i++){
Object o = list.get(i);
String o1 = (String) o;
if("world".equals(o1)){
list.add("hadoop");
}
}
//这里在使用的时候,要注意重新创建一个新的迭代器,原来修改的数据依旧在list中,需要一个新的迭代器来输出。
ListIterator listIterator1 = list.listIterator();
while (listIterator1.hasNext()){
Object next = listIterator1.next();
String next1 = (String) next;
System.out.println(next1);
}
我是酷酷的涛,感谢观看!!!