泛型
泛型简介
泛型是jdk1.5使用的新特性。
泛型的好处:- 将运行时的异常提前至了编译时。
- 避免了无谓的强制类型转换 。
泛型在集合中的常见应用:
ArrayList<String> list = new ArrayList<String>(); //true 推荐使用。 ArrayList<Object> list = new ArrayList<String>(); //false 必须一致 ArrayList<String> list = new ArrayList<Object>(); //false //以下两种写法主要是为了兼顾新老系统的兼用性问题。 ArrayList <String > list = new ArrayList(); //true ArrayList list = new ArrayList<String>(); //true
注意: 泛型没有多态的概念,左右两边的数据类型必须要一致,或者只是写一边的泛型类型。推荐使用: 两边都写泛型。
自定义泛型
自定义泛型就是一个数据类型的占位符或者是一个数据类型的变量。
方法上自定义泛型:
修饰符 <声明自定义的泛型>返回值类型 函数名(使用自定义泛型 ...){
}
在泛型中不能使用基本数据类型,如果需要使用基本数据类型,那么就使用基本数据类型对应的包装类型。
byte----> Byte
short---> Short
int----> Integer
long----> Long
double ----> Double
float -----> Float
boolean-----Boolean
char-------》 Character
方法泛型注意的事项:
1. 在方法上自定义泛型,这个自定义泛型的具体数据类型是在调用该方法的时候传入实参时确定具体的数据类型的。
2. 自定义泛型只要符合标识符的命名规则即可, 但是自定义泛型我们一般都习惯使用一个大写字母表示。 T Type E Element
泛型类
泛型类:
泛型类的定义格式:
class 类名<声明自定义泛型>{
}
泛型类要注意的事项:
1. 在类上自定义泛型的具体数据类型是在使用该类的时候创建对象时候确定的。
2. 如果一个类在类上已经声明了自定义泛型,如果使用该类创建对象 的时候没有指定 泛型的具体数据类型,那么默认为Object类型
3. 在类上自定义泛型不能作用于静态的方法,如果静态的方法需要使用自定义泛型,那么需要在方法上自己声明使用。
案例:
注意下面案例使用的时候是Integer
class MyArrays<T>{
//元素翻转
public void reverse(T[] arr){
for(int startIndex = 0, endIndex = arr.length-1 ; startIndex<endIndex ; startIndex++,endIndex--){
T temp = arr[startIndex];
arr[startIndex] = arr[endIndex];
arr[endIndex] = temp;
}
}
}
public static void main(String[] args) {
Integer[] arr = {10,12,14,19};
MyArrays<Integer> tool = new MyArrays<Integer>();
tool.reverse(arr);
System.out.println("数组的元素:"+tool.toString(arr));
MyArrays<String> tool2 = new MyArrays<String>();
String[] arr2 = {"aaa","bbb","ccc"};
tool2.reverse(arr2);
ArrayList<String> list = new ArrayList<String>();
}
泛型接口
泛型接口
泛型接口的定义格式:
interface 接口名<声明自定义泛型>{ }
泛型接口要注意的事项:
- 接口上自定义的泛型的具体数据类型是在实现一个接口的时候指定的。
- 在接口上自定义的泛型如果在实现接口的时候没有指定具体的数据类型,那么默认为Object类型,不能改成其他类型。
需求: 目前我实现一个接口的时候,我还不明确我目前要操作的数据类型,我要等待创建接口实现类 对象的时候我才能指定泛型的具体数据类型。
如果要延长接口自定义泛型 的具体数据类型,那么格式如下:
格式: public class Demo4<T> implements Dao<T>{ }
泛型上下限
泛型的上下限:
需求1: 定义一个函数可以接收接收任意类型的集合对象, 要求接收的集合对象只能存储Integer或者是Integer的父类类型数据。
需求2: 定义一个函数可以接收接收任意类型的集合对象, 要求接收的集合对象只能存储Number或者是Number的子类类型数据。
泛型中通配符:?
? super Integer : 只能存储Integer或者是Integer父类元素。 泛型的下限
? extends Number只能存储Number或者是Number类型的子类数据。 泛型上限
双列集合Map
——–| Map 如果是实现了Map接口的集合类,具备的特点: 存储的数据都是以键值对的形式存在的,键不可重复,值可以重复。
———–| HashMap
———–| TreeMap
———–| HashtableMap接口的方法:
添加: put(K key, V value) putAll(Map<? extends K,? extends V> m) 删除 remove(Object key) clear() 获取: get(Object key) size() 判断: containsKey(Object key) containsValue(Object value) isEmpty()
注意 map.put(null, null)后使用isEmpty判断是不为空的,即false
Map的迭代
keySet() values() entrySet()示例:
public class Demo3 { public static void main(String[] args) { Map<String,String> map = new HashMap<String, String>(); //添加方法 map.put("汪峰", "章子怡"); map.put("文章", "马伊琍"); map.put("谢霆锋","张柏芝"); map.put("成龙", "林凤娇"); /* //map集合中遍历方式一: 使用keySet方法进行遍历 缺点: keySet方法只是返回了所有的键,没有值。 Set<String> keys = map.keySet(); //keySet() 把Map集合中的所有键都保存到一个Set类型的集合对象中返回。 Iterator<String> it = keys.iterator(); while(it.hasNext()){ String key = it.next(); System.out.println("键:"+ key+" 值:"+ map.get(key)); } //map集合的遍历方式二: 使用values方法进行遍历。 缺点: values方法只能返回所有的值,没有键。 Collection<String> c = map.values(); //values() 把所有的值存储到一个Collection集合中返回。 Iterator<String> it = c.iterator(); while(it.hasNext()){ System.out.println("值:"+ it.next()); } */ //map集合的遍历方式三: entrySet方法遍历。 Set<Map.Entry<String,String>> entrys = map.entrySet(); Iterator<Map.Entry<String,String>> it = entrys.iterator(); while(it.hasNext()){ Map.Entry<String,String> entry = it.next(); System.out.println("键:"+ entry.getKey()+" 值:"+ entry.getValue()); } } }
Map接口实现类
HashMap
往HashMap添加元素的时候,首先会调用键的hashCode方法得到元素的哈希码值,然后经过运算就可以算出该元素在哈希表中的存储位置。
情况1: 如果算出的位置目前没有任何元素存储,那么该元素可以直接添加到哈希表中。
情况2:如果算出 的位置目前已经存在其他的元素,那么还会调用该元素的equals方法与这个位置上的元素进行比较,如果equals方法返回的是false,那么该元素允许被存储,如果equals方法返回的是true,那么该元素被视为重复元素,不允存储。
注意:如果出现了相同键,那么后添加的数据的值会取代之前的值
TreeMap
TreeMap 要注意的事项:
- 往TreeMap添加元素的时候,如果元素的键具备自然顺序,那么就会按照键的自然顺序特性进行排序存储。
- 往TreeMap添加元素的时候,如果元素的键不具备自然顺序特性, 那么键所属的类必须要实现Comparable接口,把键的比较规则定义在CompareTo方法上。
- 往TreeMap添加元素的时候,如果元素的键不具备自然顺序特性,而且键所属的类也没有实现Comparable接口,那么就必须在创建TreeMap对象的时候传入比较器。
注意:实现比较接口后,比较相等时,即键重复,这时候,新的值会取代旧的值
HashTable(不重要)
集合的工具类
Collections
Collections 和Collection的区别
一个是集合工具类,一个是集合常用方法
排序: sort(list) sort(list, comparator) 如果不具备自然顺序,要加入比较器 查找: binarySearch(list , key) 二分查找 binarySearch(list, key , Comparator) 最大最小值: max(Collection) max(Collection, comparator) min(Collection) min(Collection, comparator) 对list集合进行反转 reverse(list) 可以将不同步的集合变成同步的集合 Set synchronizedSet(Set<T> s) Map synchronizedMap(Map<K, V> m) List synchronizedList(List<T> list)
数组工具类:Arrays
常用方法
二分查找,数组要有序
binarySearch(int []) binarySearch(double[])
数组排序
sort(int []) sort(char[])
将数组变成字符串
toString(int [])
复制数组
copyOf()
复制部分数组
copyOfRange(origianl, from, to)
将数组变成集合
List asList(T[]);
比较数组元素是否一致(比较对应位置)
euqals(int[], int[]);
示例
Integer[] arr = {10, 8, 6, 9}; Integer[] arr2 = Arrays.copyOf(arr, 6); //注意这里缺的两个值是null,不是零,对象默认初始值是null