跳至主要內容

集合

HeChuangJun约 1343 字大约 4 分钟

Collection

集合与数组的异同

  • 数组的长度是固定的。集合的长度是可变的。
  • 数组可以存储基本数据类型和引用数据类型;集合中存储的元素必须是引用类型数据
  • 数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型
  • 集合中存储其实都是对象的地址
  • 集合中可以存储基本数值吗?可以通过基本类型包装类,自动装箱操作存储
  • 没指定<>时,元素存储时自动提升为Object。取出时要使用元素的特有内容,必须向下转型
  • 如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常
  • Iterator接口使用<>控制迭代元素的类型就不需要强转了.获取到的元素直接就是元素类型

Iterable

# ArrayList迭代
for (int i = 0; i < list.size(); i++) {
	String str = list.get(i);
}
for (Iterator<String> it2 = coll.iterator(); it2.hasNext();) {
	System.out.println(it2.next());
} 
Iterator<String> it=list.iterator();
while(it.hasNext()){
	String str=it.next();
	it.remove();//遍历删除
}

# Vector枚举迭代
Enumeration<String> en=list.elements();
while(en.hasMoreElements()){
	String str=en.nextElement();
}
# Map迭代
# 推荐使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。keySet 其实是遍历了2次,一次是转为Iterator对象,另一次是从 hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高

①Entry键值对对象方式
Map<String, String> map = new HashMap<String,String>();
Iterator<Map.Entry<String,String>> it = map.entrySet().iterator();
while(it.hasNext()){
	Map.Entry<String,String> entry = it.next();//得到每一对对应关系
	String key = entry.getKey();//通过每一对对应关系获取对应的key
	String value = entry.getValue();//通过每一对对应关系获取对应的value
	System.out.println(key+"="+value);
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {  
	System.out.println("Key=" + entry.getKey() + ",Value =" +entry.getValue());  
}

②遍历键找值方式
Map<String, String> map = new HashMap<String,String>();
Iterator<String> it =map.keySet().iterator();
while(it.hasNext()){
	String key = it.next();//得到每一个key
	String value = map.get(key);//通过key获取对应的value
}

for (String key : map.keySet()) {
	System.out.println("key:" + key + ",value:" + map.get(key));
}

③遍历所有的value
for (String value : map.values()) {
	System.out.println("value:" + value);
}
map.forEach((key, value) -> {
	System.out.println("key=" + key + ",value=" + value);
});
# 增强for:没有索引,不能操作容器里面的元素
for(元素类型  变量名 : 数组或者集合 ){
	sop(变量);//相当于直接每次循环将集合或者数组中的元素赋给变量
}

泛型

  • 泛型实现了参数化类型的概念,使代码可以应用于多种类型
  • 泛型可以用于内部类
  • 泛型概念
    • 指明了集合中存储数据的类型 <数据类型>(安全简单)。在编译的时候检查类型安全,避免了迭代时类型强转的麻烦
  • 泛型声明
    • 泛型类 修饰符 class 类名<代表泛型的变量> {}
    • 泛型方法 修饰符 <代表泛型的变量> 返回值类型 方法名(参数){} public <T> T[] toArray(T[] a){}
    • 泛型接口 public interface List <E>{abstract boolean add(E e);}
  • 泛型擦除:使得泛化的客户端可以用非泛化的类库来使用
    • 泛型只在编译时存在,编译后就被擦除,在编译之前我们就可以限制集合的类型,起到作用
    • 例如:ArrayList<String> al=new ArrayList<String>();编译后:ArrayList al=new ArrayList();
    • 获得泛型声明所声明的类型参数:TypeVariable<Class<T>>[] typeParameters = al.getClass().getTypeParameters();
  • 通配符和泛型的限定:为了传入泛型后能做到调用具体类型的方法,必须做限定
    • Iterator<?> it = coll.iterator()泛型的通配,匹配所有的数据类型,被擦除成Object
    • <? extends Employee> 限制的是父类, 上限限定, 可以传递Employee,传递他的子类对象,被擦除成Employee
    • <? super Employee> 限制的是子类, 下限限定, 可以传递Employee,传递他的父类对象,被擦除成Employee
    • <? extends class & interface>//多个限定
  • 元组
    • 将一组对象之间打包存储于其中的一个单一对象,这个容器对象允许读取其中元素,但是不允许向其中存放新的对象
    • 元组可以有任意长度,元组中的对象可以是任意不同的类型,
    • 元组可以实现一次方法调用返回多个对象,并且在编译期就能确保类型安全。当然也可以创建一个对象,持有返回的多个对象
public class TwoTuple<A,B>{
	public final A first;
	public final B second;
	public TwoTuple(A a,B b){
		this.first = a;
		this.second = b;
	}
}
  • 泛型类型参数推断
    • 声明变量的的时候已经指明了参数类型,初始化对象时还需指定(jdk7后不用)Map<String,Object> myMap = new HashMap<String,Object>();jdk7后=>HashMap<String,Object> map = new HashMap<>();
  • 泛型构造器
//泛型必须有无参构造函数
public class Generator<T> {
    private Class<T> type;
    public Generator(Class<T> type){this.type = type;}
    public T get(){
        try {
            return (T) type.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
    public T[] getArray(int size){
        return (T[]) Array.newInstance(this.type,size);
    }
    public static <T> Generator<T> create(Class<T> type){
        type.getTypeParameters();
        return  new Generator<>(type);
    }
	public static void main(String[] args) {
        System.out.println(Generator.create(Test.class).get());
		System.out.println(Generator.create(Test.class).getArray(10));
    }
}

动态获得子类的类型

//在父类(IBaseDaoImpl)的构造方法中动态获得entityClass字节码对象
public IBaseDaoImpl() {
  //获得T
  ParameterizedType Superclass = (ParameterizedType) this.getClass().getGenericSuperclass();
  //获得父类上声明的泛型数组
  Type[] actualTypeArguments = Superclass.getActualTypeArguments();
  entityClass=(Class<T>) actualTypeArguments[0];
}