java.uti.Collection接口
Collection是所有集合的顶级接口,里面规定了所有集合都必须具备的方法
集合和数组一样都用来保存一组元素,但是集合提供了操作元素的相关方法,使用更便捷
Collection下面有两个常见的子接口
java.util.List:可重复集合
java.util.Set:不可重复集合
重复指的是元素是否可以重复,重复元素的判断依据是靠元素自身equals比较的结果
/*
* 数组在创建时要指定元素,后面要添加还必须扩容
*/
Collection c=new ArrayList();
/**最好存类型一样的元素*/
/*
* boolean add(E e)
*/
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);
/*
* size表示集合元素的个数,元素有多少个,集合就有多长
* length表示数组的长度,并不是数组元素的个数,例如长度为10的数组中的元素个数可能是0个或多个
* int size()
* 返回当前集合元素个数
*/
int size=c.size();
System.out.println("size:"+size);
/*
* boolean isEmpty()
* 判断该集合是否为空集(不含有任何元素)
*/
boolean isEmpty=c.isEmpty();
System.out.println("isEmpty:"+isEmpty);
/*
* void clear()
* 清空集合
*/
c.clear();
System.out.println(c);
System.out.println("size:"+c.size());
System.out.println("isEmpty:"+isEmpty);
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);
泛型在集合中使用广泛,而泛型在集合中是用来约束集合的元素类型
/**创建集合对象*/
Collection<String> c=new ArrayList<String>();
/**往集合中添加元素*/
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);
// /**通过迭代器遍历集合*/
// Iterator<String> it=c.iterator();
// while (it.hasNext()) {
// String o=it.next();
// System.out.println(o);
// }
/**遍历集合*/
for (String string : c) {
System.out.println(string);//获取每个集合元素
}
Collection<String> c1=new ArrayList<>();
c1.add("java");
c1.add("c");
c1.add("c++");
System.out.println("c1:"+c1);//c1:[java, c, c++]
Collection<String> c2=new HashSet<>();
c2.add("php");
c2.add("js");
c2.add("java");
System.out.println("c2:"+c2);//c2:[java, php, js]
/*
* 将给定集合中的所有元素添加到当前集合中
*/
c1.addAll(c2);//把c2中的元素都加到c1中
System.out.println("c1:"+c1);//c1:[java, c, c++, java, php, js]
Collection<String> c3=new ArrayList<>();
c3.add("php");
c3.add("c++");
// c3.add("android");
System.out.println("c3:"+c3);//c3:[php, c++, android]
/*
* 全包含:判断当前集合是否包含给定集合中的所有元素
*/
boolean contains=c1.containsAll(c3);
System.out.println("全包含:"+contains);//全包含:true
/*
* 删除交集:将c1中与c3相同元素删除
*/
c1.removeAll(c3);
System.out.println("c1:"+c1);//c1:[java, c, java, js]
判断当前集合是否包含给定元素
boolean contains(Object o)
判断依据是依靠自身equals比较的结果
Collection c=new ArrayList();
c.add(new Point(1,2));
c.add(new Point(3, 4));
c.add(new Point(5, 6));
c.add(new Point(1, 2));
Point p=new Point(1,2);
Boolean contain=c.contains(p);
System.out.println("包含:"+contain);
集合的遍历
集合遍历元素采用迭代器模式
Iterator iterator()
该方法可以获取一个用来遍历当前集合元素的迭代器
java.util.Iterator接口
迭代器接口规定了所有迭代器遍历集合元素的相关操作,每个集合都提供了一个用于遍历自身元素的迭代器实现类。
而我们无需记住他们的名字,只当它们为Interator去使用即可
迭代器遍历集合遵循“问、取、删”的顺序遍历,其中删除不是必须的
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 o=(String)it.next();
System.out.println(o);
if ("#".equals(o)) {
/*
* 迭代器在遍历时不允许通过集合自身方法增删元素,否则会抛出异常
*/
//c.remove();
//迭代器的remove删除的是
it.remove();
}
System.out.println(o);
}
JDK1.5 之后推出了一个特性:增强型for循环,也称为新循环
新循环与传统for循环不同,它是用来遍历集合或数组使用
String[] arr= {"one","two","three","four","five"};
//普通for循环
for (int i = 0; i < arr.length; i++) {
String string = arr[i];
System.out.println(string);
}
//增强型for循环
for (String string : arr) {
System.out.println(string);
}
//遍历集合
Collection c=new ArrayList();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);
/*
* 新循环这个特性是java编译器认可,而非虚拟机
* 编译器在编译源代码时若发现我们使用新循环遍历数组时,会将代码改为普通的for循环遍历
* 若发现使用新循环遍历集合,则会改为使用迭代器方式遍历
* 注意:使用新循环遍历集合时,不要通过集合的方法增删元素
*/
for (Object o : c) {
String str=(String)o;
System.out.println(str);
}
Collection c=new ArrayList();
c.add(new Point(1,2));
c.add(new Point(3, 4));
c.add(new Point(5, 6));
// c.add(new Point(1, 2));
Point p=new Point(1,2);
c.add(p);
System.out.println("p:"+p);
System.out.println("c:"+c);
/*
* 集合的remove()方法是删除集合中与给定元素equals比较为true的元素,并且只删掉一个
* 集合存的是元素的引用
*/
c.remove(p);//删除元素直接掉用remove方法即可,而数组还要去找到那个元素然后删掉
System.out.println("c:"+c);
线程安全的集合
集合的工具类:java.util.Collections提供了一组静态方法,可以将给定集合转换为线程安全的
我们常用的集合实现类:ArrayList,LinkedList,HashSet它们都不是线程安全的,如果存在并发访问时,要将它们转换
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
System.out.println(list);
/*
* 将给定的List集合转换为线程安全的
*/
list=Collections.synchronizedList(list);
System.out.println(list);
Set<String> set = new HashSet<>(list);
System.out.println(set);
/*
* 将给定的set集合转换为线程安全的
*/
set=Collections.synchronizedSet(set);
System.out.println(set);
/*
* API手册也有说明,一个线程安全的集合也不与迭代器遍历集合的操作互斥
* 所以若多线程“同时”操作集合存在遍历和增删元素时,需要自行维护它们之间的互斥关系。
* 可参考聊天室Server端操作
*/
泛型
JDK1.5推出的一个新特性
泛型也称为参数化类型,允许我们在使用一个类时,指定其属性,方法参数,方法返回值的类型,使得该类的使用更符合需求,更灵活
public class Type<T> {
/*
* 泛型是编译器认可,而非虚拟机
* 所有泛型定义的地方最终会被编译器改为Object
* 下面有泛型定义的地方会改为:
* private Object x;
*
* public Type(Object x, Object y)
*
* public Object getX()
*
* public void setX(Object x)
* 所以泛型的原型就是Object
*/
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 + ")";
}
}
/*
* 使用泛型时,编译器会做两件事
* 1.在给泛型类型赋值时,编译器会检查该值类型是否符合泛型要求
* 例如:
* t1.setX(2);
* 对于t1而言,由于泛型指定为Integer,因此编译器会检查setX()传递的参数是否为整数,不是则编译不通过
* 2.在获取泛型类型的值时,编译器会添加向下造型的代码将其转换为泛型指定类型
* int x1=t1.getX();
* 实际编译后会改为:
* int x1=(Integer)t1.getX();
* 当然这里还触发了自动拆箱,所以实际改为了
* int x1=((Integer)t1.getX()).intValue();
*/
Type<Integer> t1=new Type<Integer>(1,2);//在创建的同时指定参数类型
t1.setX(2);
int x1=t1.getX();
System.out.println("x1:"+x1);
System.out.println("t1:"+t1);
泛型在使用时可以不指定,若不指定则默认为原型Object
但通常有泛型的地方都应当指定泛型的实际类型
Type<Integer> t1=new Type<Integer>(1,2);//在创建的同时指定参数类型
t1.setX(2);
int x1=t1.getX();
System.out.println("x1:"+x1);
System.out.println("t1:"+t1);
Type t2=t1;
System.out.println("t2:"+t2);
t2.setX("一");//此处把x类型改为了String
Object x2=t2.getX();
System.out.println("x2:"+x2);
System.out.println("t2:"+t2);
System.out.println("t1:"+t1);
// x1=t1.getX();//类造型异常---此处x的类型是String,而x1是int型,两者不能互转
System.out.println("x1:"+x1);
System.out.println("t1:"+t1);
附件:作为集合元素测试集合相关操作
/**
* 作为集合元素测试集合相关操作
*
* @author Administrator
*
*/
public class Point {
private int x;
private int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}