Collection集合
-
java.util.Collection 集合
集合可以保存一组元素,并且提供了操作元素的相关方法。
-
常用的子接口:
- java.util.List 线性表 可重复 并且有序
- java.util.Set 不可重复
- 是否重复指的是元素是否可以重复,而判定是否重复的标准是依靠元素自身equals比较的结果。
public class CollectionDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
/*
* boolean add(E e)
* 将给定元素添加到集合当中,当成功添加后方法
* 会返回true,添加失败返回false
*/
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);
/*
* int size()
* 获取当前集合元素个数
*/
int size = c.size();
System.out.println("size:"+size);
/*
* boolean isEmpty()
* 判断当前集合是否为空集(不含有任何元素)
*/
boolean isEmpty = c.isEmpty();
System.out.println("是否为空集:"+isEmpty);
/*
* void clear()
* 清空集合
*/
c.clear();
System.out.println("集合已清空");
System.out.println("size:"+c.size());
System.out.println("isEmpty:"+c.isEmpty());
System.out.println(c);
}
}
-
集合只能存放引用类型元素,并且保存的元素的引用(地址)
public class CollectionDemo2 { public static void main(String[] args) { Collection c = new ArrayList(); Point p = new Point(1, 2); c.add(p); System.out.println("p:"+p); System.out.println("c:"+c); p.setX(2); System.out.println("p:"+p); System.out.println("c:"+c);//[(2,2)] } }
-
集合操作
public class CollectionDemo3 { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("java"); c1.add("c"); c1.add("c++"); Collection c2 = new ArrayList(); c2.add("android"); c2.add("ios"); /* * boolean addAll(Collection c) * 添加完毕后,当前集合元素发生改变则返回true */ c1.addAll(c2); System.out.println("c1:"+c1); Collection c3 = new ArrayList(); c3.add("java"); c3.add("ios"); // c3.add("php"); /* * boolean containsAll(Collection c) * 判断当前集合是否包含给定集合中的所有元素 */ boolean contains = c1.containsAll(c3); System.out.println("全包含:"+contains); /* * boolean removeAll(Collection c) * 删除当前集合与给定集合的公有元素 */ c1.removeAll(c3); System.out.println("c1:"+c1); } }
-
boolean contains(Object o) 判断当前集合是否包含给定元素
public class ContainsDemo { public static void main(String[] args) { Collection c = new ArrayList(); c.add(new Point(1, 2)); c.add(new Point(3, 4)); c.add(new Point(5, 6)); System.out.println(c); Point p = new Point(1, 2); /* * contains的判定标准是看给定的对象p是否与 * 集合现有元素存在equals比较为true的,若有 * 则认为包含,否则为不包含。 * 所以元素equals方法决定这集合判断包含的结果 */ boolean contains = c.contains(p); System.out.println("包含:"+contains); } }
-
遍历 Collection提供了统一的遍历集合的方式:迭代器模式 对应方法: Iterator iterator( ) 该方法可以返回一个用于遍历当前集合的迭代器
public class IteratorDemo { 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"); System.out.println(c); //获取迭代器 Iterator it = c.iterator(); /* * boolean hasNext() * 判断集合是否还有下一个元素可以迭代。 * 问的过程 */ while(it.hasNext()){ /* * E next() * 通过迭代器获取集合下一个元素。 * 取的过程 */ String str = (String)it.next(); System.out.println(str); /* * 在遍历的过程中删除#操作 * 需要注意: * 迭代器有一个要求,就是在遍历的过程中不得 * 使用集合的方法增删元素,否则会抛出异常。 * 可以通过迭代器自身提供的remove方法删除 * 元素。该方法不需要传入参数,删除的是通过 * next方法取出的元素。 */ if("#".equals(str)){ it.remove(); } } System.out.println(c); } }
-
增强for循环,也称为新循环或for each 新循环是用来遍历集合或数组使用的,所以功能上不取代传统for循环的工作,并且该特性是编译器认可,而非虚拟机认可。编译器最终会将使用新循环遍历改为传统遍历方式。
public class NewForDemo1 { public static void main(String[] args) { String[] array = {"one","two","three","four"}; 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); } } } public class NewForDemo2 { public static void main(String[] args) { Collection c = new ArrayList(); c.add("one"); c.add("two"); c.add("three"); c.add("four"); c.add("five"); System.out.println(c); /* * 新循环遍历集合最终会被编译器改编为迭代器遍历 * 所以在使用新循环遍历集合的过程中不要通过集合 * 的方法增删元素。 */ for(Object o : c){ String str = (String)o; System.out.println(str); } } }
-
删除元素
public class RemoveDemo { public static void main(String[] args) { Collection c = new ArrayList(); c.add(new Point(1, 2)); c.add(new Point(3, 4)); c.add(new Point(5, 6)); System.out.println(c); Point p = new Point(1, 2); /* * 删除也是删除集合中与给定元素equals比较为true的元素, * 对于List而言,重复元素只删除第一个 */ c.remove(p); System.out.println(c); } }
-
集合的线程安全
集合的工具类Collections可以将现有的集合转换为一个线程安全的,对于集合自身的操作如:add,
remove等都可以保证并发安全。但是API手册也有说明,一个并发安全的集合也不与使用迭代器遍历操作做互斥,这意味着并发操作中遍历与集合自身操作并非并发安全的,需要自行维护互斥关系。
List的常用实现类:ArrayList,LinkedList都不是线程安全的,可以通过Collections将List转换为线程安全的
public class SyncCollectionDemo { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("one"); list.add("two"); list.add("three"); System.out.println(list); list = Collections.synchronizedList(list); System.out.println(list); //HashSet也不是线程安全的 Set<String> set = new HashSet<String>(list); set = Collections.synchronizedSet(set); System.out.println(set); } }
-
泛型
泛型是JDK1.5之后推出的另一个特性,泛型也称为参数化类型,指在使用某个类时为其属性,方法参数,方法返回值 的类型指定实际类型。这在实际开发中可以大大提高代码的灵活度。
泛型应用最广的地方就是集合,用来约束集合的元素类型。泛型的实际类型为Object,当不指定泛型时,默认就使用原型Object。
泛型允许调用者使用时决定一个类中属性,参数,返回值等的类型,从而提高代码的灵活性。
public class Type<T> { private T x; private T y; public Type(T x, T y) { super(); this.x = x; this.y = y; } public T getX() { return x; } public void setX(T x) { this.x = x; } public T getY() { return y; } public void setY(T y) { this.y = y; } @Override public String toString() { return "("+x+","+y+")"; } } public class TypeDemo { public static void main(String[] args) { //创建集合时通过泛型约束集合的元素类型 Collection<String> c = new ArrayList<String>(); c.add("one");//此时集合只能存放String c.add("two"); c.add("three"); c.add("four"); System.out.println(c); //获取迭代器时也通过泛型告知迭代器元素类型 Iterator<String> it = c.iterator(); while(it.hasNext()){ //获取元素时无需再造型 String str = it.next(); System.out.println(str); } //新循环也可以直接使用String接收集合元素了 for(String str:c){ System.out.println(str); } } } //泛型应用 public class TypeDemo2 { public static void main(String[] args) { /* * Type中的x,y都是泛型<T>,而泛型的实际类型是 * Object,所以x,y实际上就是Object类型 * * 在使用时,指定T为Integer,那么编译器会依靠该类型 * 检查对x,y赋值时的实际值的类型是否符合要求。 * 并且在获取它们的值时,编译器会自动添加造型代码 */ Type<Integer> t = new Type<Integer>(1,2); //编译器会检查实参是否满足泛型所指定类型的要求 t.setX(2); //获取时,无需造型(编译器会自动补全) int x = t.getX(); System.out.println("x:"+x); System.out.println(t); Type<Double> t2 = new Type<Double>(1.1,2.2); t2.setX(2.2); double x2 = t2.getX(); System.out.println("x2:"+x2); System.out.println(t2); Type<String> t3 = new Type<String>("一","二"); t3.setX("三"); String x3 = t3.getX(); System.out.println("x3:"+x3); System.out.println(t3); } } //泛型是编译器认可,非虚拟机认可。 public class TypeDemo3 { public static void main(String[] args) { Type<Integer> t1 = new Type<Integer>(1,2); //编译器会检查实参类型是否符合泛型要求 t1.setX(3); //编译器会自动补充造型回Integer的代码 int x1 = t1.getX(); System.out.println("x1:"+x1); System.out.println("t1:"+t1); //当不指定泛型时,编译器默认认为是原型Object Type t2 = t1; System.out.println("t2:"+t2); t2.setX("一"); System.out.println("t2:"+t2); //类造型异常! x1 = t1.getX(); System.out.println("x1:"+x1); System.out.println("t1:"+t1); } }