一。集合的相关应用
1.1 将一个集合加到另一个集合上
boolean addAll(Collection c)
将给定集合中的所有元素添加到当前集合中。调用方法之后只要c1集合发生变化就返回true
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1);
Collection c2 = new HashSet();
c2.add("java");
c2.add("android");
c2.add("ios");
System.out.println("c2:"+c2);
/*
* boolean addAll(Collection c)
* 将给定集合中的所有元素添加到当前集合中。调用方法之后只要c1集合发生变化就返回true
*
* 此处若使用add方法则是将c2整体内容视为一个元素添加到c1中
*/
c1.addAll(c2);
//c2.addAll(c1);//重复的元素不能放入Set集合两次
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
1.2 判断是否为子集
boolean containsAll(Collection c)
判断当前集合是否包含给定集合中的所有元素
/*
* boolean containsAll(Collection c)
* 判断当前集合是否包含给定集合中的所有元素
*
* c1.contains(c3)
* 则是看当前集合c1中包不包含一个元素是c3集合,此时是吧c3当成一个元素看待
* 由于c1集合中没有一个元素是一个集合类型,因此返回值为false
*/
Collection c3 = new ArrayList();
c3.add(".net");
c3.add("ios");
System.out.println("c3:"+c3);
boolean contains = c1.containsAll(c3);
boolean contains1 = c1.contains(c3);
System.out.println("c1是否包含c3所有元素:"+contains);//t
System.out.println("c1是否包含c3集合元素:"+contains1);//f
1.3 删除交集
removeAll(Collection c)
删除交集,即:删除当前集合中与给定集合的共有元素。但给定的集合不受影响
/*
* removeAll(Collection c)
* 删除交集,即:删除当前集合中与给定集合的共有元素。
* 但给定的集合不受影响
*
* 此处若使用remove方法也是删除一个c3集合的元素。
*/
c1.removeAll(c3);//删除交集,删除c1当中与c3集合的共有元素
System.out.println("c1:"+c1);//c1元素减少了
System.out.println("c3:"+c3);//c3元素没有变化
1.4 集合的遍历
Collection提供了统一 的遍历集合元素的操作:迭代器
*
方法:
Iterator iterator()
该方法会获取一个用于遍历当前集合的迭代器
*
java.util.Iterator接口
该接口是迭代器接口,规定了迭代器遍历集合的相关操作,不同的集合实现类都提供了 一个用于遍历自身元素的迭代器实现类。我们无需知道每种集合提供的迭代器实现类 的名字,只需要当它是Iterator看待即可。迭代器遍历集合的步骤遵循:问、取、删
- 其中的删除元素不是遍历过程中的必须操作
boolean hasNext()方法
判断集合是否还有下一个元素可以遍历(第一次遍历时相当于询问有没有第一个元素)
E next()方法
获取集合下一个元素,同样的,第一次调用时获取的是第一个元素
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("tree");
System.out.println(c);
//获取遍历该集合的迭代器
Iterator it = c.iterator();
/*
* boolean hasNext()
* 判断集合是否还有下一个元素可以遍历(第一次遍历时相当于询问有没有第一个元素)
*/
while(it.hasNext()){
/*
* E next()
* 获取集合下一个元素,同样的,第一次调用时获取的是第一个元素
*/
String str = (String)it.next();
System.out.println(str);
//System.out.println(it.next());//出现两次.next()意味调用了两次,易出异常
//遍历的过程中删除所有#
if("#".equals(str)){
/*
* 迭代器有一个要求,遍历的过程不可以通过集合的方法增删元素
* 否则遍历过程中会抛出异常:ConcurrentModificationException
*/
// c.remove(str);
/*
* 迭代器提供了remove方法,删除的是通过next获取的元素
*/
it.remove();//只能删除操作,没有添加方法
}
}
System.out.println(c);
1.5 List集合
java.util.List集合
List集合可以保证保存重复元素,并且有序。提供了一套通过下标操作元素的方法。
常用实现类:
- java.util.ArrayList:内部由数组实现,查询性能好
- java.util.LikList:内部由链表实现,增删元素性能更好
如不对性能有特别苛刻要求,一般都使用ArrayList
List集合常用方法:
E get(int index)
获取指定下标处对应的元素
E set(int i,E e)
将给定元素设置到指定位置,返回值为原位置对应的元素(被替换的元素)
重载的add方法
void add(int index,E e);
将给定元素插入到指定位置
重载的remove方法
E remove(int index)
删除并返回指定位置上的元素
List<String>list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("tree");
list.add("four");
System.out.println(list);
/*
* E get(int index)
* 获取指定下标处对应的元素
*/
//获取List集合中的第三个元素
String str = list.get(2);
System.out.println(str);
for(int i=0;i<list.size();i++){
str = list.get(i);
System.out.println(str);
}
/*
* E set(int i,E e)
* 将给定元素设置到指定位置,返回值为原位置对应的元素(被替换的元素)
*/
//[one,2,tree,four]
String old = list.set(1, "2");//指定的下标如果超范围会抛异常
System.out.println(list);//[one,2,tree,four]
System.out.println(old);//two
/*
* 重载的add方法
* void add(int index,E e);
* 将给定元素插入到指定位置
*/
//[one,2,3,tree,four]
list.add(2,"3");
System.out.println(list );
/*
* 重载的remove方法
* E remove(int index)
* 删除并返回指定位置上的元素
*/
//[one,2,3,tree,four]——>[one,2,3,four]
old = list.remove(3);
System.out.println(list);
System.out.println(old);//tree
List subList(int start,int end )
获取指定范围的子集
List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
System.out.println(list);
List<Integer> subList = list.subList(3, 8);
System.out.println(subList);
//将subList中的元素每个扩大10倍
for(int i=0;i<subList.size();i++){
subList.set(i, subList.get(i)*10);
}
System.out.println(subList);
/*
* 对子集的操作就是对原集合对应的操作
*/
System.out.println(list);
/*
* 删除list集合中2——8元素
*/
list.subList(2, 9).clear();
System.out.println(list);
1.6 在集合操作中对子集的改变会反馈到原始的集合中
二、增强型for循环
JDK5推出时,推出了一个特性:增强型for循环。
该特性使得我们可以用相同的语法遍历数组和集合。
*
语法:
for(接收元素的变量定义 : 集合或数组){
循环体
}
注:
使用新循环遍历数组时会被编译器改为使用普通for循环遍历
新循环遍历集合会被编译器改为迭代器遍历
JDK5推出时还推出了一个新特性:泛型
泛型又称为参数化类型,可以在使用一个类时指定该类中某个属性或者非法的参数,返回 值的类型。使得使用时更加灵活。
泛型在集合中广泛应用,用于指定集合中的元素类型。支持泛型的类在使用时若不指定泛型的实际类型时,默认为Object
String[] array = {"123","456","789","10JQ"};
// for(int i=0;i<array.length;i++){
// String str = array[i];
// System.out.println(str);
// }
/*
* 新循环语法是编译器认可的而非虚拟机,我们使用新循环遍历数组时
* 会被编译器改为使用普通for循环遍历。
*/
for(String str:array){
System.out.println(str);
}
/*
* Collection<e>,集合定义时有个泛型类型E,那么使用时可以指定E表示的
* 实际类型是什么,下面的例子中实际类型指定的为Integer
*/
Collection<Integer> c = new ArrayList<Integer>();
c.add(1);//自动装箱特性
c.add(2);
c.add(3);
c.add(4);
// c.add("one");//编译不通过,编译器会检查传入的参数是否为Integer
System.out.println(c);
//迭代器同样需要指定泛型,类型与遍历的集合指定的泛型一致即可。
Iterator<Integer> it = c.iterator();
while(it.hasNext()){
Integer i = it.next();//获取元素时无需再造型
System.out.println(i);
}
/*
* 新循环遍历集合会被编译器改为迭代器遍历,因此使用新循环遍历集合的过程
* 中不能通过集合的方法增删元素。
*/
for(Integer i:c){//集合指定泛型后,这里可以直接用泛型指定类型接收
System.out.println(i);
}
/*
* 使用新循环(迭代器)遍历集合不是并发安全的,也不会和集合 的增删元素
* 互斥,因此在多线程使用下,要自行维护多个线程对该集合的操作,避免一个
* 线程遍历的过程中其他线程进行增删元素操作,否则遍历这里会抛出异常
*
*/
三、foreach方法
JDK8之后集合推出了一个新的方法:foreach,可以使用lambda表达式进行遍历
如果一个集合不是并发安全的集合,使用foreach方法遍历是可以和增删元素互斥的。
注:
哪怕是一个并发安全的集合,迭代器方式遍历也不和增删元素互斥,只能自行使用同步块维护互斥关系。
*
- 我们常用的集合实现类:ArrayList,LinkedList,HashSet都不是线程安全的
//JDK7 之后,实例化集合时,泛型可以只写<>,而不用再写一遍实际类型
Collection<Integer>c = new ArrayList<>();
c.add(1);
c.add(2);
c.add(3);
c.add(4);
c.add(5);
System.out.println(c);
for(Integer i: c){
System.out.println(i);
}
c.forEach(
(i)->System.out.println(i)
);
/*
* 将现有的集合转换为并发安全的集合
*/
List<String>list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
System.out.println(list);
//将给定的list集合转换为线程安全的list集合
list = Collections.synchronizedList(list);
System.out.println(list);
/*
* 同样的也有synchronizedSet方法,可将一个set集合转换为线程安全的
*/
//创建一个线程安全的集合
List <String>list = Collections.synchronizedList(new ArrayList<>());
list.add("1");
list.add("2");
list.add("3");
list.add("4");
Thread t1 = new Thread(){
public void run(){
//新循环遍历(迭代器)
// for(String s:list){
// System.out.println(getName()+":"+s);
// try{
// Thread.sleep(1000);
// }catch(InterruptedException e){
//
// }
// }
//使用foreach进行遍历
list.forEach(//foreach会和下面线程调用add方法互斥保证并发安全
(e)->{
System.out.println(getName()+":"+e);
try{
Thread.sleep(1000);
}catch(InterruptedException e1){
}
}
);
System.out.println("线程遍历结束");
}
};
Thread t2 = new Thread(){
public void run(){
try{
Thread.sleep(2000);
}catch(InterruptedException e){
}
System.out.println(getName()+"开始添加新元素");
list.add("5");
System.out.println(getName()+"元素添加完毕");
}
};
t1.start();
t2.start();
四、数组和集合间的相互转换
4.1数组转换为集合
使用数组的方法Arrays中的asList方法,可将一个数组转换为一个List集合。
不支持转换为Set集合,因为Set集合不能放重复元素。
String[] array = {"one","two","tree","four"};
System.out.println("array:"+Arrays.toString(array));
List <String> list = Arrays.asList(array);
System.out.println("list:"+list);
/*
* 修改集合元素急速修改原数组对应的元素
*/
list.set(1, "2");
System.out.println("list:"+list);
System.out.println("array:"+Arrays.toString(array));
//数组为定长的,故add和remove方法都不适用,会抛出异常
// list.add("five");//下面两行代码执行不到
// System.out.println("list:"+list);
// System.out.println("array:"+Arrays.toString(array));
//单独创建一个集合,将数组转换的集合元素导入就可以任意增删操作了
/*
* 所有的集合都支持一个参数为Collection的构造方法,作用是在
* 创建当前集合的同时包含给定集合的所有元素。
*/
//创建list2集合的同时包含list所有元素
List<String>list2 = new ArrayList<>(list);
System.out.println("List2:"+list2);
list2.add("five");
System.out.println("list2:"+list2);
4.2 集合转换为数组
**toArray()**方法
Collection<String> c = new ArrayList<>();
c.add("one");
c.add("two");
c.add("tree");
c.add("four");
System.out.println(c);
//Object[]arr1 = c.toArray();
String []arr2 = c.toArray(new String[c.size()]);
System.out.println(arr2.length);
System.out.println(arr2.toString());//会输出乱码
System.out.println(Arrays.toString(arr2));
练习
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
* 集合间的操作
* @author 毛
*
*/
public class CollectionDemo4 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1);
Collection c2 = new HashSet();
c2.add("java");
c2.add("android");
c2.add("ios");
System.out.println("c2:"+c2);
/*
* boolean addAll(Collection c)
* 将给定集合中的所有元素添加到当前集合中。调用方法之后只要c1集合发生变化就返回true
*
* 此处若使用add方法则是将c2整体内容视为一个元素添加到c1中
*/
c1.addAll(c2);
//c2.addAll(c1);//重复的元素不能放入Set集合两次
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
/*
* boolean containsAll(Collection c)
* 判断当前集合是否包含给定集合中的所有元素
*
* c1.contains(c3)
* 则是看当前集合c1中包不包含一个元素是c3集合,此时是吧c3当成一个元素看待
* 由于c1集合中没有一个元素是一个集合类型,因此返回值为false
*/
Collection c3 = new ArrayList();
c3.add(".net");
c3.add("ios");
System.out.println("c3:"+c3);
boolean contains = c1.containsAll(c3);
boolean contains1 = c1.contains(c3);
System.out.println("c1是否包含c3所有元素:"+contains);//t
System.out.println("c1是否包含c3集合元素:"+contains1);//f
/*
* removeAll(Collection c)
* 删除交集,即:删除当前集合中与给定集合的共有元素。
* 但给定的集合不受影响
*
* 此处若使用remove方法也是删除一个c3集合的元素。
*/
c1.removeAll(c3);//删除交集,删除c1当中与c3集合的共有元素
System.out.println("c1:"+c1);//c1元素减少了
System.out.println("c3:"+c3);//c3元素没有变化
/*5*/
c1.addAll(c3);
boolean b5 = c1.containsAll(c3);
c1.removeAll(c3);
/*4*/
c1.addAll(c3);
boolean b4 = c1.containsAll(c3);
c1.removeAll(c3);
/*3*/
c1.addAll(c3);
boolean b3 = c1.containsAll(c3);
c1.removeAll(c3);
/*2*/
c1.addAll(c3);
boolean b2= c1.containsAll(c3);
c1.removeAll(c3);
/*1*/
c1.addAll(c3);
boolean b1 = c1.containsAll(c3);
c1.removeAll(c3);
}
}
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("tree");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c);
//获取遍历该集合的迭代器
Iterator it = c.iterator();
/*
* boolean hasNext()
* 判断集合是否还有下一个元素可以遍历(第一次遍历时相当于询问有没有第一个元素)
*/
while(it.hasNext()){
/*
* E next()
* 获取集合下一个元素,同样的,第一次调用时获取的是第一个元素
*/
String str = (String)it.next();
System.out.println(str);
//System.out.println(it.next());//出现两次.next()意味调用了两次,易出异常
//遍历的过程中删除所有#
if("#".equals(str)){
/*
* 迭代器有一个要求,遍历的过程不可以通过集合的方法增删元素
* 否则遍历过程中会抛出异常:ConcurrentModificationException
*/
// c.remove(str);
/*
* 迭代器提供了remove方法,删除的是通过next获取的元素
*/
it.remove();//只能删除操作,没有添加方法
}
}
System.out.println(c);
/*5*/
Collection c5 = new ArrayList();
c5.add("one");
c5.add("#");
c5.add("two");
c5.add("#");
c5.add("tree");
System.out.println(c5);
Iterator it5 = c5.iterator();
while(it5.hasNext()){
String str = (String)it5.next();
System.out.println(str);
if("#".equals(str)){
it5.remove();//只能删除操作,没有添加方法
}
}
System.out.println(c5);
/*4*/
Collection c4 = new ArrayList();
c4.add("1");
c4.add("!");
c4.add("2");
System.out.println(c4);
Iterator it4 = c4.iterator();
while(it4.hasNext()){
String str = (String)it4.next();
System.out.println(str);
if("!".equals(str)){
it4.remove();
}
}
System.out.println(c4);
/*3*/
Collection c3 = new ArrayList();
c3.add("a");
c3.add("@");
c3.add("b");
System.out.println(c3);
Iterator it3 = c3.iterator();
while(it3.hasNext()){
String s = (String)it3.next();
System.out.println(s);
if("@".equals(s)){
it3.remove();
}
}
System.out.println(c3);
/*2*/
Collection c2 = new ArrayList();
c2.add("1");
c2.add("a");
c2.add("~");
System.out.println(c2);
Iterator it2 = c2.iterator();
while(it2.hasNext()){
String s = (String)it2.next();
System.out.println(s);
if("~".equals(s)){
it2.remove();
}
}
System.out.println(c2);
/*1*/
Collection c1 = new ArrayList();
c1.add("1");
c1.add("a");
c1.add("~");
System.out.println(c1);
Iterator it1 = c1.iterator();
while(it1.hasNext()){
String s = (String)it1.next();
System.out.println(s);
if("~".equals(s)){
it1.remove();
}
}
System.out.println(c1);
/*5*/
String[] array5 = {"123","456","789","10JQ"};
for(String str:array5){
System.out.println(str);
}
Collection<Integer> c5 = new ArrayList<Integer>();
c5.add(1);//自动装箱特性
c5.add(2);
c5.add(3);
System.out.println(c5);
Iterator<Integer> it5 = c5.iterator();
while(it5.hasNext()){
Integer i5 = it5.next();//获取元素时无需再造型
System.out.println(i5);
}
for(Integer i5:c5){//集合指定泛型后,这里可以直接用泛型指定类型接收
System.out.println(i5);
}
/*4*/
String[]array4 = {"1","2","3"};
for(String str:array4){
System.out.println(str);
}
Collection <Integer>c4 = new ArrayList<Integer>();
c4.add(1);
c4.add(2);
System.out.println(c4);
Iterator <Integer>it4=c4.iterator();
while(it4.hasNext()){
System.out.println(it5.next());
}
for(Integer i4:c4){
System.out.println(i4);
}
/*3*/
String[]a3 = {"1","2"};
for(String s:a3){
System.out.println(s);
}
Collection<Integer>c3 = new ArrayList<>();
c3.add(1);
c3.add(3);
Iterator<Integer>it3 = c3.iterator();
while(it3.hasNext()){
System.out.println(it3.next());
}
for(Integer i3:c3){
System.out.println(i3);
}
/*2*/
String[]a2 = {"45","78"};
for(String s:a2){
System.out.println(s);
}
Collection <Integer>c2 = new ArrayList<>();
c2.add(2);
c2.add(4);
Iterator <Integer>it2 = c2.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
for(Integer i2:c2){
System.out.println(i2);
}
/*1*/
String[]a1 = {"45","78"};
for(String s:a1){
System.out.println(s);
}
Collection <Integer>c1 = new ArrayList<>();
c1.add(2);
c1.add(4);
Iterator <Integer>it1 = c1.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
for(Integer i1:c1){
System.out.println(i1);
}