1 泛型机制
集合中可以存放不同类型的对象,是因为将所有对象都看作Object类型放入的,所以从集合中取出的元素也都是Object类型,而为了表达元素的真实数据类型,通常需要使用强制类型转换,但是强制类型转换可能会导致类型转换异常。
为了解决上面提到的问题,java5开始引入泛型机制,在集合名称右侧使用<数据类型>的方式来明确该集合所存放的元素的数据类型,若放入其他数据类型的元素,编译会报错(泛型只在编译时期有效,在运行时期不区分类型)
泛型机制的底层原理:泛型的本质就是参数化类型,将数据类型当作参数进行传递,而其中E相当于形式参数负责占位,使用集合时<>中的数据类型当作实参,用来给形式参数E进行初始化,使得集合中所有的E都被实际参数所替换,由于实际参数可以传递各种各样的广泛的数据类型,因此称为泛型。
//E当作形式参数,负责占位
public interface List<E>{
}
//在使用集合时,将<>中的String当作实际参数传递给E进行初始化,从而E代表String
List<String> lt1=new LinkedList<>();
2 自定义泛型
自定义泛型有:自定义泛型接口、自定义泛型类、自定义泛型方法,下面会介绍这三种自定义泛型
- 自定义泛型接口:和普通接口相比,自定义泛型接口就是在类名后面加上类型参数列表,所以类型参数可以有一个或多个
,比如public interface List<E,T,......>
-
自定义泛型类:和自定义泛型接口一样,在普通类的后面加上了类型参数列表,类型参数同样可以有一个或多个,具体实例如public class Student<E,T,......>,需要注意的是在实例化自定义泛型类时,需要给出具体的数据类型,并且数据类型只能是引用类型;父类有泛型时,子类可以选择保留泛型也可以选择指定泛型类型;子类是“富二代”,不仅可以指定或保留父类泛型,还可以添加自己的泛型。
-
自定义泛型方法:自定义泛型方法就是在普通方法输入参数时,输入的是泛型参数,而不再是具体的参数,在使用泛型方法时也就需要对泛型参数进行实例化。泛型方法的语法格式是:访问权限 <泛型> 返回值类型 方法名(泛型标识 参数名称){方法体;};在静态方法中使用泛型参数时,需要将静态方法定义为泛型方法。
//定义方法打印数组中的所有元素,因为不知道数组的数据类型,所以需要用泛型,写成泛型方法 public <T1> void printArry(T1[] arr){ for(T1 a:arr){ Syste.out.println(a); } }
3 泛型在继承上的体现
示例代码如下:
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
String str=map.put(1,"java");
System.out.println("原来的value数值是"+str);
map.put(2,"pyhton");
System.out.println("Map集合的元素是:"+map);
boolean b=map.containsKey(1);
System.out.println("Map集合中存在key值"+b);
b=map.containsValue("python");
System.out.println("Map集合中存在value值"+b);
str=map.get(2);
System.out.println("取出的值是"+str);
str=map.remove(2);
System.out.println("集合中删除的值是"+str);
Set<Integer> s1=map.keySet();
for(Integer i:s1){
System.out.println(i+"="+map.get(i));
}
Collection<String> collection=map.values();
for(String s:collection){
System.out.println("s="+s);
}
Set<Map.Entry<Integer,String>> s2=map.entrySet();
for(Map.Entry<Integer,String> in:s2){
System.out.println(in);
}
}
}
元素添加到HashMap集合原理:
- 使用元素的key调用hashCode方法获取对应的哈希码值,再有某种哈希算法计算在数组中的索引位置。
- 若该位置没有元素,则直接将该键值对放入
- 若该位置已经存在元素,则使用key与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入
- 若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素依次比较
- 若相等则将对应的value修改,否则将键值对直接放入即可
8 Collections类
Java.util.Collections类主要提供对集合操作或者返回集合的静态方法
Collectons常用方法如下:
| 方法声明 | 功能介绍 |
|---|---|
| static <T extends Object & Comparable <? super T>>T max(Collection<? extends T> Coll) | 根据元素的自然顺序返回给定集合的最大元素 |
| static T max(Collection<? extends T> Coll,Comparator <? super T> comp) | 根据指定比较器引发的顺序返回给定集合的最大元素 |
| static <T extends Object & Comparable <? super T>>T min(Collection<? extends T> Coll) | 根据元素的自然顺序返回给定集合的最小元素 |
| static T max(Collection<? extends T> Coll,Comparator <? super T> comp) | 根据指定比较器引发的顺序返回给定集合的最小元素 |
| static void copy(List< ? super T > dest,List< ? extends T> src ) | 将第一个列表中的所有元素复制到另一个列表中 |
| static void reverse(List<?> list) | 反转指定列表中元素的顺序 |
| static void shuffle(List<?> list) | 使用默认的随机源随机置换指定的列表 |
| static <T extends Comparable <? super T>> void sort(List list) | 根据其元素的自然顺序将指定列表按升序排序 |
| static void sort(List list,Comparator <? super T> c) | 根据指定比较器指定的顺序对指定列表进行排序 |
| static void swap(List< ?> list,int i,int j) | 交换指定列表中指定位置的元素 |
实例代码:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionsTest {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(11,22,33,44,55);
System.out.println("集合中最大值是:"+ Collections.max(list));
System.out.println("集合中最小值是:"+ Collections.min(list));
System.out.println("集合中元素是:"+list);
Collections.reverse(list);
System.out.println("集合中元素反转后是:"+list);
Collections.swap(list,0,2);
System.out.println("交换后集合是:"+list);
Collections.sort(list);
System.out.println("排序后的集合是"+list);
Collections.shuffle(list);
System.out.println("随机置换后集合是:"+list);
List<Integer> list1= Arrays.asList(new Integer[6]);
Collections.copy(list1,list);
System.out.println("list集合元素是"+list);
System.out.println("list1集合元素是"+list1);
}
}