1. Iterator 接口
Iterator接口是Java集合框架的成员,主要用于遍历集合的元素(又叫迭代器)。
hasNext() 如果被迭代的集合元素还有没遍历,则返回true
next() 返回集合里的下一个元素
remove() 删除集合里上一次next方法返回的元素
原理:
当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集合元素本事没有影响。
当使用Iterator来迭代访问Collection集合元素时,Collection集合里的元素不能被修改,只能通过remove方法删除上次next方法返回的集合元素才可以,否则报java.util.ConcurrentModificationException异常(并发修改异常)。
2. 泛型
示例:
List list = new ArrayList();
//这是未引入参数化类型时的写法,list集合中可以存储不同类型的元素,如此便有了安全隐患,编译器不能保证你取值时的转型(拆箱)一定正确。
list.add(“qqyumidi”);
list.add(“corn”);
list.add(100);
list.add(true);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i);
System.out.println("name:" + name);
}
传统集合接收和返回Object对象(不好的)
a.有装箱和拆箱操作,影响性能
b.任何类型的数据就可以接收,无法做类型控制
c.拆箱操作,即强制类型转换,带来了安全隐患,可能导致代码出异常,无法保证类型安全
d.类型转换使得代码编写更加繁琐
2.1 泛型概念
泛型,即“参数化类型”,就是一个编译器可以自动定制作用于特定类型上的类。
简单的说就是,原本集合中用来处理的通用类型为Object,而使用了参数化类型后,编译器会自动的将Object参数的类型修改为你传递给它的参数化类型。
例如:上例运行时内存中List类中的Object属性,全被替换为String的。
作用:提高程序健壮性,简化代码
符号:T、E、K、V
2.2 泛型接口
//定义一个泛型接口
public interface Action<T> {
public T execute();
}
2.2.2 未传入泛型实参时:
//与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
public class UserAction<T> implements Action<T>{
@Override
public T execute() {
return null;
}
}
如果不声明泛型,编译器会报"Unknown class"异常。
public class UserAction implements Action<User>{
@Override
public User execute() {
return null;
}
}
2.2.2 传入泛型实参时
定义一个类实现这个接口,虽然我们只创建了一个泛型接口Action<T>
但是我们可以为T传入无数个实参,形成无数种类型的Action接口。
在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
//传入泛型实参为String时
public class UserAction implements Action<String> {
private String[] strArr = {"Apple", "Banana", "Pear"};
@Override
public String execute() {
Random rand = new Random();
return strArr[rand.nextInt(3)];
}
}
//传入泛型实参为Integer时
public class UserAction implements Action<Integer> {
private int[] intArr = {1,2,3,4,5,6};
@Override
public Integer execute() {
Random rand = new Random();
return intArr[rand.nextInt(3)];
}
}
2.3 泛型类
class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>{
private 泛型标识 /*(成员变量类型)*/ var;
.....
}
示例:创建时为类设置泛型,在实例化泛型类时,必须指定T的具体类型
public class Action<T>{
private T key; //key的类型为T,而T的类型由外部指定
public Action(T key){ //构造方法key的类型也为T,T的类型由外部指定
this.key = key;
}
public T getKey(){ ///getKey()的返回值类型为T,T的类型由外部指定
return key;
}
}
//泛型的类型参数只能是引用类型(包括自定义类),不能是值类型。
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Action<Integer> integerAction = new Action<Integer>(123456);
//传入的实参类型需与泛型的类型参数类型相同,即为String.
Action<String> stringAction = new Action<String>("key_vlaue");
System.out.println("泛型测试", "key is " + integerAction.getKey());
System.out.println("泛型测试", "key is " + stringAction.getKey());
2.4 泛型方法
//首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
public <T> T showKeyName(Action<T> action){
System.out.println("Action key :" + action.getKey());
//当然这个例子举的不太合适,只是为了说明泛型方法的特性。
T test = action.getKey();
return test;
}
2.5 泛型通配符 ?
public class Test {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
//这里传入的参数类型即有String、Int…
getData(name);
getData(age);
getData(number);
}
//此处"?"是类型实参,而不是类型形参
//可以把"?"看成所有类型的父类。是一种真实的类型
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
}
2.6. 总结
(1)泛型的默认值是Object。
(2)泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。
(3)泛型的好处:
a. 类型安全
b. 消除强制类型转换
c. 提高性能。
3. 装箱 与 拆箱
值类型 -> 引用类型 = 装箱
Integer a = new Integer(1);
引用类型 -> 值类型 = 拆箱
Integer b = a + 10;
jdk1.5之后引入了自动装箱及自动拆箱功能
4. List集合去重问题
4.1 循环list中的所有元素然后删除重复
public static List removeDuplicate(List list){
for ( int i = 0 ; i < list.size() - 1 ; i ++ ) {
for ( int j = list.size() - 1 ; j > i; j – ) {
if (list.get(j).equals(list.get(i))) {
list.remove(j);
}
}
}
return list;
}
4.2 通过HashSet踢除重复元素
public static List removeDuplicate(List list) {
HashSet h = new HashSet(list);
list.clear();
list.addAll(h);
return list;
}
4.3 把list里的对象遍历一遍,用list.contain(),如果不存在就放入到另外一个list集合中
public static List removeDuplicate(List list){
List listTemp = new ArrayList();
for(int i=0;i<list.size();i++){
if(!listTemp.contains(list.get(i))){
listTemp.add(list.get(i));
}
}
return listTemp;
}