容器也叫集合collection,用来存放对象或基本类型数据,数组是一种容器,但是不够灵活强大,不满足管理组织数据的需求,例如容量可扩等。
容器的整体结构
接口间的区别
List | Set | |
---|---|---|
是否有序 | 有序 | 无序 |
是否可重复 | 可重复 | 不可重复 |
List
三个实现类的区别
ArrayList | LinkedList | Vector | |
---|---|---|---|
底层实现 | 数组 | 双向链表 | 数组 |
查询效率 | 高 | 低 | 低 |
增删效率 | 低 | 高 | 低 |
线程安全 | 不安全 | 不安全 | 安全 |
相关方法
常用方法 Collection接口定义
- add 增加元素
- isEmpty 测试是否非空
- size 返回长度
- contains 是否包含
- remove 移除(不等于删除,被移除元素仍存在内存中,不在list中而已)
- toArray 转换成数组
-
List独有方法 索引相关
add(index, element) 指定位置加元素
- remove(index) 删除指定位置元素
- set(index, element) 设置指定位置元素
- get(index) 获取指定位置元素
indexOf(element) lastIndexOf(element) 从正反方向查找元素
容器间元素处理方法
A.containsAll(B) A容器是否包含B容器所有元素
- A.addAll(B) A容器增加B容器存在的所有元素
- A.removeAll(B) A容器去除B容器存在的所有元素
A.retainAll(B) A容器取AB容器的交集(改变A)
Set
常用类HashSet
无序,顺序无意义,无标记
- 基本用法就是相等元素不会重复加入
- 常用方法与list一致,在collection接口中被定义
不可重复的核心为equals方法,是否重复由对象的equals方法确定
Map
与list、set不同,map以键key值value对的形式成对存储
- 键值对均为对象通过键来标识,键不可重复(equals判定),基本数据类型会被自动装箱
Map接口实现类有HashMap、TreeMap、HashTable、Properties等
接口方法
size 返回键值对数量
- isEmpty 是否为空
- containsKey(key) 是否包含key
- containsValue(avlue) 是否包含值value
- get(key) 获取容器中键key对应的值对象
- put(key,value) 存入键值对,如果键重复,旧值会被替换
- remove(key) 从容器中移除key对应的键值对
- putAll(map) 将容器map中所有的键值对添加至目标容器
- clear 清空容器
- keySet 返回存储key的Set容器
- values 返回values集合
- entrySet 返回存放Map.Entry类型的键值对Set容器
HashMap和HashTable
|
| HashMap | HashTable | | —- | —- | —- | | 线程安全 | 不安全 | 安全 | | 效率 | 高 | 低 | | key为null | 允许 | 不允许 |
泛型
基本概念
- 泛型本质就是数据类型的参数化,处理的数据类型不是固定的,可以作为参数传入
- <数据类型>只能是引用类型
- 优点是代码可读性好、程序安全(编译时期没有警告,运行时期就不会出现ClassCastException异常)
- 泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息,设计类型转换仍然是普通的类型转换
- 泛型主要就是方便程序员的编写以及更好的安全性检测,约定标记如下: | 泛型标记 | 对应单词 | 说明 | | —- | —- | —- | | E | Element | 在容器中使用,表示容器中的元素 | | T | Type | 表示普通的JAVA类 | | K | Key | 表示键,例如:Map中的键Key | | V | Value | 表示值 | | N | Number | 表示数值类型 | | ? | | 表示不确定的JAVA类型 |
容器中使用泛型
- 限制容器存取内容类型(给容器贴标签)
- 使容器的实用规范、简答、安全
```java
// list1中只能存放String类型
List
list1 = new ArrayList<>();
// set1中只能存放Integer类型
List
// map1中只能存放键值均为String类型的键值对
Map
<a name="DAnzn"></a>
## 自定义泛型(泛型类、泛型接口、泛型方法)
```java
// 定义
class Generic1<T>{
public T fn(T obj){
System.out.println(obj);
return obj;
}
public <N> void fn1(N obj){
System.out.println(obj);
}
}
interface MyList<E> {
int size();
boolean isEmpty();
void add(E e);
E get(int index);
}
// 使用
Generic1<Integer> g1 = new Generic1<>();
g1.aa(22);
Generic1<String> g2 = new Generic1<>();
g2.aa("22");
class MyArrayList<E> implements MyList<E> {
// ...方法代码
}
泛型标记和泛型限定
public class GenericTest {
// 限定Dog以及子类
public static void test01(List<? extends Dog> list){}
// 限定Dog以及父类
public static void test02(List<? super Dog> list){}
}
三种容器遍历方式
Collection接口遍历
// 通过索引遍历,只能用于List,因为Set没有索引
for(int i = 0; i<list1.size(); i++){
String temp = list1.get(i);
}
// 通过增强for循环 (List、Set)
for(String temp:list1){
System.out.println(temp)
}
// 通过迭代器Iterator对象 (List、Set)
for(Iterator<String> iter = list1.iterator();iter.hasNext();){
String temp = iter.next();
System.out.println(temp);
}
Map接口遍历
// 遍历Map(遍历Key、遍历Value)
// 遍历键
Set<String> keySet1 = map1.ketSet();
for(String temp:keySet1){
System.println("key:" + temp + "value:" + map1.get(temp))
}
// 遍历值
Collections<String> values1 = map1.values();
for(String temp:values1){
System.println("value:" + temp)
}
// 使用EntrySet遍历
Set<Map.EntrySet<String,String>> entrySet1 = map1.entrySet();
for(Map.EntrySet es:entrySet1){
System.println("key:" + es.getKey() + "value:" + es.getValue())
}