集合
约 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<>();
- 声明变量的的时候已经指明了参数类型,初始化对象时还需指定(jdk7后不用)
- 泛型构造器
//泛型必须有无参构造函数
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];
}