目录
Collection集合提供的方法
- boolean addAll(Collection c);添加集合c
- boolean containsAll(Collection c);判断包含
- boolean removeAll(Collection c);删除包含
/**
* boolean addAll(Collection c)
* 将给定集合中的所有元素添加到集合中,当前集合发生了改变就返回true
*/
Collection c = new ArrayList();
c.add("java");
c.add(".net");
Collection list = new ArrayList();
list.add("java");
list.addAll(c);
Collection set1 = new HashSet();
set1 .add(c);
//System.out.println(list);//[java, java, .net] list集合允许重复
System.out.println(set1);//[[java, .net]] set集合大部分不允许重复
/*
boolean containsAll(Collection c)
判断当前集合是否包含给定集合中的所有元素
包含 返回true 否则返回false
*/
boolean b = list.containsAll(c);
System.out.println(b);//true
/*
boolean removeAll(Collection o) 删交集
*/
list.add("ios");
System.out.println(c);//[java, java, .net]
System.out.println(list);//[java, java, .net, ios]
boolean b1 = list.removeAll(c);
System.out.println(list);//[ios]
迭代器遍历
- 迭代器遍历
- Iterator iterator()
- 注意:不要再foreach里对集合进行add/remove 后果是灾难性的,阿里手册
- remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
/**
* 集合的遍历
* Collection 提供了统一的遍历集合方式:迭代器模式
*
* Iterator iterator()
* 该方法会获取一个用于遍历当前集合元素的迭代器
*
* java.util.Iterator接口,迭代器接口,定义了迭代器遍历集合的相关操作
* 不同的集合都实现了一个用于遍历自身元素的迭代器实现类,我们无需记住它们的名字,用多态的
* 角度把他们看做为了Iterator即可。
* 迭代器遍历集合遵循的步骤为:问、取、删。其中删除元素不是必要操作
*/
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
Iterator i = c.iterator();
while (i.hasNext()){
String str = (String)i.next();
System.out.print(str);
/**
* 迭代器要求遍历的过程中不得通过集合的方法增、删元素,否则会抛出异常
*/
/*c.remove("#");*/
/*
迭代器提供了remove方法,将next方法得到的元素从集合中删除
删除多个元素用迭代器遍历删除
删除一个元素,不用遍历,直接调用集合删除方法
*/
if("#".equals(str)){
i.remove();
}
System.out.println();
}
System.out.print(c);
}
增强for循环
- 新循环:jdk5后推出的新特性(只能用来遍历),内部是用迭代器维护的;使得我们可以使用相同的语法遍历集合或数组
- 底层仍然是通过for循环实现的;而遍历集合时,底层是通过迭代器实现的。
- 新循环
某一个线程在调用迭代器 it.hasNext();方法,突然没时间了
另一个线程调用了list.remove(.)方法,这时候,再回来执行迭代器,就会报错
所以list是并发安全的时候,则迭代器遍历的时候必须加synchronized的 并锁上allOut对象- 即:
- 遍历用的是迭代器 调用的是Iterator的对象,而不是list的方法,
- 所以迭代器遍历的时候,list集合不能自己做增删元素操作,会出现并发安全状况的,会报错,应该是空指针,因为没有这个元素了,是null,再去操作肯定会报错
- 即:
- 也就是说,当线程执行到for循环的时候对集合,突然没时间了,然后做了删除操作,这个时候再回来遍历,就会有并发安全问题
- 详细查看socket聊天室
/*
* 语法:
* for(元素类型 变量名 :集合或数组){
* 循环体
* }
*/
public static void main(String[] args) {
String[] arg = {"one","two","three","four","five"};
for(String str : arg){
System.out.println(str);
}
Collection c = new ArrayList();
((ArrayList) c).add("one");
((ArrayList) c).add("two");
((ArrayList) c).add("three");
((ArrayList) c).add("five");
/*
1、集合里每个元素都是Object类型
2、新循环的语法是编译器认可的,而不是虚拟机。编译器在编译代码时会把新循环遍历数组
改为普通的for循环遍历
*/
for (Object o :c){
String s = (String)o;
System.out.println(s);
}
}
泛型
- jdk5推出的特性,又称为参数化类型:用来指定集合中的元素类型
/**
* jdk5之后推出的另一个新特性:泛型
* 泛型也称为参数化类型,允许我们在使用一个类时指定它当中的属性、方法参数或返回值类型
* 泛型在集合中被广泛使用,用来指定集合中的元素类型。
* 有泛型支持的类在使用时若不指定泛型的具体类型则默认为原型Object
*/
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();//指定E为String类型
//add(E e),add方法中参数的类型就是E,这里就相当于是String类型了
c.add("123");
c.add("one");
//新循环是编译器认可的,JVM不认可,也就是编译器在编译的时候会编译回来
//新循环遍历集合,编译器会编译成迭代器的模式,所以在新循环里不能操作,只能用来遍历
//如果想操作,那就还用迭代器
/*
新循环遍历集合就是迭代器遍历。编译器会改为迭代器
注意:不要在使用新循环遍历集合的过程中使用集合的方法增删元素,否则会抛出异常
*/
for(String s : c){
System.out.println(s);
}
Iterator<String> it = c.iterator();
while (it.hasNext()){
String str = it.next();
System.out.println(str);
}
}