目录
一. Map接口下的实现类
1. HashMap
1.1 HashMap常用方法
2. TreeMap
2.1 TreeMap常用方法
3. Hashtable
3.1 Hashtable常用方法
4.Map集合的遍历
4.1 根据键找值
4.2 利用map中的entrySet()方法
二.Collections类
1.Collections类中的常用方法
三. 泛型
1. 为什么使用泛型
2. 什么是泛型
3. 泛型类
4. 从泛型类派生子类
5. 泛型接口
6.类型擦除
一. Map接口下的实现类
特点:
(1)Map接口下的实现类都是以键值对的形式存储
(2)键不能重复,值可以重复
(3)通过键可以找到对应的值,但不能通过值找对应的键,因为值不唯一
(4)一个键只能映射到一个值
1. HashMap
HashMap存储数据时键是无序的,就和HashSet一样,无序指的是不会按照插入顺序进行存储
1.1 HashMap常用方法
V put(K, key,V value) | 向map中添加元素 |
V remove(Object key) | 删除键是指定元素的键值,返回对应的值 |
clear() | 清空map中的元素 |
boolean isEmpty() | 判断集合是否为空,为空返回true,不为空返回false |
boolean containsKey(Object key) | 判断是否包含指定的键,包含返回true,不包含返回false |
boolean containsValue(Object value) | 判断是否包含指定的值,包含返回true,不包含返回false |
V get(K key) | 根据键找对应的值 |
int size() | 返回map中有几组键值对 |
2. TreeMap
TreeMap底层仍旧是树形结构,键可以排序,只不过要求存储键的类要实现Comparable接口实现compareTo()方法
2.1 TreeMap常用方法
V put(K, key,V value) | 向map中添加元素 |
V remove(Object key) | 删除键是指定元素的键值,返回对应的值 |
clear() | 清空map中的元素 |
boolean isEmpty() | 判断集合是否为空,为空返回true,不为空返回false |
boolean containsKey(Object key) | 判断是否包含指定的键,包含返回true,不包含返回false |
boolean containsValue(Object value) | 判断是否包含指定的值,包含返回true,不包含返回false |
V get(K key) | 根据键找对应的值 |
int size() | 返回map中有几组键值对 |
3. Hashtable
Hashtable和HashMap基本类似,但Hashtable的方法中都用synchronized修饰了,加了一把锁表示线程安全,就和ArrayList和Vector,StringBuffer和StringBuilder一样,但不同的是HashMap键和值都可以添加null关键字,而Hashtable键和值都不能添加null关键字,
3.1 Hashtable常用方法
V put(K, key,V value) | 向map中添加元素 |
V remove(Object key) | 删除键是指定元素的键值,返回对应的值 |
clear() | 清空map中的元素 |
boolean isEmpty() | 判断集合是否为空,为空返回true,不为空返回false |
boolean containsKey(Object key) | 判断是否包含指定的键,包含返回true,不包含返回false |
boolean containsValue(Object value) | 判断是否包含指定的值,包含返回true,不包含返回false |
V get(K key) | 根据键找对应的值 |
int size() | 返回map中有几组键值对 |
4. Map集合的遍历
4.1 根据键找值
public class HashMapDemo3 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("a","aa");
map.put("b","bb");
map.put("w","ww");
//HashMap键值都可以存储null
map.put("a",null);
map.put(null,"aaaaa");
map.put(null,null);
System.out.println(map);
//map遍历
//方式1:先拿到所有的键,遍历键,根据键找值
Set<String> keyset = map.keySet();
for(String key:keyset){
System.out.println(key+":"+map.get(key));
}
}
}
利用map中的keySet()方法拿到所有的键,遍历键,根据map中的get()方法拿到值
4.2 利用map中的entrySet()方法
public class HashMapDemo3 {
public static void main(String[] args) {
//方式2 推荐的遍历方式
Set<Map.Entry<String,String>> entries = map.entrySet();
for(Map.Entry<String,String> entry:entries){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
二. Collections类
1. Collections类中的常用方法
addAll(Collection<? super T> c,T... elements) | 将emements可变参数中的元素全部添加到集合中 |
binarySearch(List<? extends Comparable<? super T>> list,T key) | 二分查找 |
sort(List list) | 对集合进行排序,默认升序 |
sort(List list, Comparator c) | 对集合进行排序,可以自定义排序规则 |
swap(List list, int i, int j) | 交换集合中的元素,i,j为下标 |
copy(List dest, List src) | 集合间的复制,注意dest.size()必须大于src.size() |
fill(List list, T obj) | 用某个值填充集合 |
max(Collection coll) | 获取集合中的最大值 |
min(Collection coll) | 获取集合中的最小值 |
replaceAll(List list, T oldVal, T newVal) | 用新值替换集合中的旧值 |
reverse(List list) | 反转集合,逆序输出 |
shuffle(List list) | 随机打乱集合中的元素顺序 |
三. 泛型
1. 为什么使用泛型
我们知道集合容器中是可以添加任意类型的元素的(Object),但要是添加任意的元素,会导致我们在遍历处理时做出很多判断同时还存在类型转换的问题,使代码变得冗余,减少代码的可读性,所以我们要使用泛型来对集合中的元素进行限制,让其只能存储一组数据类型相同的元素
2. 什么是泛型
泛型就是将数据类型当做参数传递(参数化类型),注意这里的数据类型只能是引用数据类型,不能传递基本数据类型,这样就可以在编译期间检查传入的参数是否是规定的类型
3. 泛型类
泛型类就是将泛型用于类的定义中,这样当我们产生该类的对象时,就需要传入一种类型,来确定类中某些成员的类型
public class Result<T,E> {
int code;
public T data;
E element;
String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
如图Result类就是一个泛型类,当new该类的对象时可以传入两个参数,用来确定data和element的数据类型,如果我们不传的话,默认是Object类型
4. 从泛型类派生子类
当我们一个类要继承一个泛型类时,为了避免父类的泛型不能被确定,所以当继承时有两种方法
1.将子类也声明为泛型类,并且和父类的泛型相同
/*
当一个类继承一个泛型类时, 将子类也声明为泛型类
public class B<T> extends A<T>
B<String> b = new B();
*/
public class A<T> {
T data;
}
public class B<T> extends A<T> {
public static void main(String[] args) {
B b = new B();
b.data="";
}
}
2.子类若不是泛型类,则在继承时需要明确指定出父类泛型的具体类型
/*
当一个类继承一个泛型类时,子类不是泛型类,
那么就必须明确父类泛型类型
public class B extends A<String>
*/
public class B extends A<String> {
public static void main(String[] args) {
B b = new B();
b.data="";
}
}
5. 泛型接口
泛型接口和泛型类的继承是一样的,可以参考上面的方式
1.一个类实现泛型接口,如果该类也是泛型类,则两者的泛型要一致
2.一个类实现泛型接口,如果该类不是泛型类,则要指明该接口泛型的具体类型
6. 类型擦除
类型擦除:泛型只是在编译期间帮助我们检查类型是否符合规定的类型,当我们在实际运行时,进入JVM前,关于泛型的一切信息就会被擦除,统一当做Object类型或上限类型处理,这就是类型擦除
public class Demo2 {
public static void main(String[] args) throws NoSuchFieldException {
Result<String,String> result2 = new Result<>();
result2.setData("abc");//虽然声明了泛型,但是实际在底层存储时,还是按照Object接收存储,这个称为类型擦除
Field data = result2.getClass().getField("data");
System.out.println(data.getType());//获取实际运行时类型
}
}
上述代码通过反射机制,获取result2中data成员变量实际运行时的类型,结果如下
可以看到result2类中的data成员变量在实际运行时并不是我们的String类型,而是Object类型