集合框架
体系介绍
集合:是java提供一套用于存储引用数据类型的容器,各个接口实现类有不同的特点,可实现数组的功能。
集合和数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本数据类型和引用数据类型,集合只能存储引用类型
Collection
collection:是List和Set的父接口,提供了一些常用的用于操作集合的增删改查的方法。
方法 | 含义 |
---|---|
add() | 添加 |
remove() | 删除 |
isEmpty() | 判断集合是否为空 |
clear() | 清空集合 |
size() | 获取集合长度 |
contians() | 查看是否包含某个元素 |
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
迭代器
iterator()
iterator.hasNext() 判断是否还有下一个
iterator.next() 下一个
iterator.remove() 删除
*/
public class CollectionsList {
public static void main(String[] args) {
Collection collection = new ArrayList();
// add() 添加元素
collection.add("西瓜");
collection.add("香蕉");
collection.add("橘子");
collection.add("葡萄");
// size() 查询Collectiony的长度
System.out.println("Collection的长度是:" + collection.size());
// remove() 删除
collection.remove("香蕉");
System.out.println("Collection的长度是:" + collection.size());
// isEmpty() 判断一下集合是否为空
System.out.println(collection.isEmpty());
// contains() 查看是否有某个值
System.out.println(collection.contains("橘子"));
// clear() 清空
// collection.clear();
// 遍历
// 迭代器 遍历 collection
Iterator iterator = collection.iterator();
// iterator.hasNext() 是否还有下一个
while(iterator.hasNext()){
// next() 下一个
String next = (String) iterator.next();
System.out.println(next);
// 在iterator 迭代器过程中中 不能使用collection.方法操作集合
// 删除 元素 iterator自带了 iterator.remove()
iterator.remove();
}
System.out.println(collection);
}
}
List接口
List子接口特点:有序,有下标,元素可以重复 。
/*
List子接口 特点: 有序 有下标 可重复
listIterator 迭代器 方法
hssNext() 是否还有下一个
next() 下一个
nextIndex() 下一个元素下标
hasPrevious() 上一个元素
previousIndex() 上一个元素下标
previous() 下一个元素
subList(fromIndex,toIndex)截取集合 包头不包尾
list.get() 根据下标获取值
*/
public class Lists {
public static void main(String[] args) {
List list = new ArrayList();
// 添加
list.add("香蕉");
list.add("苹果");
list.add("橘子");
list.add("橙子");
// 添加到下标为0的位置
list.add(0,"水果");
System.out.println(list);
// 删除
list.remove(0);
list.remove("苹果");
System.out.println(list);
// 截取集合 subList(fromIndex,toIndex) 包头不包尾
List subList = list.subList(0, 2);
System.out.println(subList);
// 判断是否包含某个元素
System.out.println(list.contains("橘子"));
// 判断是否为空
System.out.println(list.isEmpty());
// 根据下标获取值
System.out.println(list.get(2));
// 获取当前集合长度
System.out.println(list.size());
// 遍历 有下标可以用for遍历
System.out.println("===============for遍历===============");
for(int i =0;i<list.size();i++){
System.out.println(list.get(i));
}
// iterator 迭代器遍历
System.out.println("===============迭代器遍历===============");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// listiterator 遍历
System.out.println("===============listiterator遍历===============");
ListIterator listIterator = list.listIterator();
// 是否还有下一个
while(listIterator.hasNext()){
// listIterator.nextIndex() 下一个元素下标 listIterator.next() 下一个元素
System.out.println(listIterator.nextIndex() + ":" + listIterator.next());
}
// listIterator 遍历 从后往前遍历
while(listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex() + ":" +listIterator.previous());
}
}
}
// remove 补充
List list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
// remove(index) 或 remove (Object)
// 如果 删除 10 这个元素 只能根据0下标来删除
// remove(10) 这样删除 是找不到下标的
// 可以remove(new Integer(10)) 把10 转换成包装类即可
list.remove(new Integer(10));
System.out.println(list.toString());
ArrayList
ArrayList特点:
有序的 ,可重复, 有下标,
查询快, 增删慢
底层是一个Object数组
运行效率快, 线程不安全
使用无参构造初始化ArrayList表示初始化一个空的数组
当我们第一次添加元素的时候,集合的长度修改为10
扩容是原来的1.5倍
删除元素也涉及到移动位置,并且删除是将元素设置为null 等待垃圾回收
ArrayList 因为有下标 查询快 可以直接根据下标来查询元素
因为有下标 增删慢 因为对集合内容的修改 必须最后保证数组的数据结构完整性。
public class ArrayLists {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("迪迦");
arrayList.add("赛罗");
arrayList.add("赛文");
arrayList.add("泰罗");
// 打印长度
System.out.println(arrayList.size());
// toString()
System.out.println(arrayList.toString());
// 修改
arrayList.set(0,"奥特之王");
System.out.println(arrayList.toString());
// 删除
arrayList.remove(3);
System.out.println(arrayList.toString());
// 查询
System.out.println(arrayList.get(1));
// 查看是否包含某个元素
System.out.println(arrayList.contains("奥特之王"));
// 判断是否为空
System.out.println(arrayList.isEmpty());
// 截取集合 包头不包尾
List list = arrayList.subList(1, 3);
System.out.println(list);
// 遍历
Iterator iterator = arrayList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// 正向遍历
ListIterator listIterator = arrayList.listIterator();
while(listIterator.hasNext()){
System.out.println("下标是:" + listIterator.nextIndex() + ":" + listIterator.next());
}
// 逆向遍历
while(listIterator.hasPrevious()){
System.out.println("下标是:" + listIterator.previousIndex() + ":" + listIterator.previous());
}
}
}
Vector
Vector特点:
- 无参构造 直接初始化一个长度为10的数组 本质还是一个数组
- 扩容是原来的两倍
- 线程安全的
Vector vector = new Vector<>();
// 添加
vector.add("苹果");
vector.add("香蕉");
vector.add("葡萄");
// 查看集合长度
System.out.println(vector.size());
// 打印数组
System.out.println(vector.toString());
// 删除
vector.remove("苹果");
// 改
vector.set(0,"橘子");
System.out.println(vector.toString());
// 根据index查询
System.out.println(vector.get(1));
// 遍历 Enumeration 枚举器
Enumeration elements = vector.elements();
while (elements.hasMoreElements()){
String s = (String )elements.nextElement();
System.out.println(s);
}
// clear 清空集合
vector.clear();
LinkedList
LinkedList提供了与ArrayList相同的API,不同的实现,还提供了独有的用于操作头部和尾部的方法。
- LinkedList是基于双向链表的实现
- 没有初始大小 也不涉及扩容
- 无序 没有下标 元素内容不能重复
- 线程不安全的
- 查询慢 增删快 因为没有下标 不需要移动元素 查询慢 同样也是因为没有下标 不能下标来一次就差找到想要的内容
方法 | 含义 |
---|---|
getFirst() | 获取链表头部 第一个元素 |
getLast() | 获取链表尾部 最后一个元素 |
removeFirst() | 删除链表头部 |
removeLast() | 删除链表尾部 |
LinkedList linkedList = new LinkedList();
// 添加
linkedList.add("苹果");
linkedList.add("香蕉");
linkedList.add("提子");
linkedList.add("橙子");
linkedList.add("葡萄");
linkedList.add("荔枝");
// 添加到链表头部
linkedList.addFirst("橘子");
// 添加到链表尾部
linkedList.addLast("菠萝");
// 获取链表头部 第一个元素
System.out.println(linkedList.getFirst());
// 获取链表尾部 最后一个元素
System.out.println(linkedList.getLast());
// 根据index获取
System.out.println(linkedList.get(1));
// 删除
linkedList.remove("橘子");
System.out.println(linkedList.toString());
// 删除链表头部
linkedList.removeFirst();
// 删除链表尾部
linkedList.removeLast();
System.out.println(linkedList.toString());
// 修改
linkedList.set(0,"奥特曼");
System.out.println(linkedList.toString());
// iterator 遍历
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// listIterator 遍历
ListIterator listIterator = linkedList.listIterator();
// 正向遍历
while(listIterator.hasNext()){
System.out.println( "下标:" + listIterator.nextIndex() + "元素:" + listIterator.next());
}
// 逆向遍历
while (listIterator.hasPrevious()){
System.out.println("下标:" + listIterator.previousIndex() + "元素:" + listIterator.previous());
}
泛型
泛型:泛型是JDK1.5引入的一个新特性,其本质是参数化类型,把类型作为参数传递
统一数据类型 方便代码的管理和扩展
常见形式:泛型类 泛型接口 泛型方法 形参 返回值
泛型表示字母可以随意写,大小写都可以,但是我们要求都大写,而且通常是单词首字母
比如:
- K key 键
- V value 值
- E element 元素
- R return 返回值
- P parameter 参数
- T type 类型
泛型相当于一个占位符 先占一个位置 不具体是什么类型 我们在实例化的时候 指定是什么类型 那么泛型就指代什么类型
泛型不能转型 泛型不能多态
好处:
- 提高代码的重用性
- 防止类型转换异常,提高代码的安全性
// 泛型类
class A<T>{
// 声明一个变量
T t;
// 泛型作为形参
public void m1(T t){
System.out.println(t);
}
// 泛型作为返回值
T m2(){
return t;
}
// 泛型方法
public <T> T m3(T t){
System.out.println(t);
return t;
}
}
public class Generic{
public static void main(String[] args) {
A<String> a = new A<>();
a.t = "Hello World";
a.m1("good");
System.out.println( a.m2());
a.m3("very good !");
}
}
// 泛型接口
interface D<T>{
// 声明一个接口 返回值泛型
T m1 ();
// 声明一个接口 参数 返回值 泛型
T m2(T t);
}
class E implements D<Integer>{
@Override
public Integer m1() {
return 520;
}
@Override
public Integer m2(Integer integer) {
return integer;
}
}
public class GenericInterface {
public static void main(String[] args) {
D e = new E();
System.out.println( e.m1());
System.out.println( e.m2(1314));
}
}
Set接口
set接口特点:无序丶无下标丶元素不可重复
方法:全部继承Collection中的方法
Set<String> set = new HashSet();
// 添加
set.add("香蕉");
set.add("葡萄");
set.add("橙子");
// size() 长度
System.out.println("set集合的长度是:" + set.size());
// 打印
System.out.println(set.toString());
// 删除 不能根据下标来删除
set.remove("橙子");
System.out.println(set.toString());
// 判断是否包含某个元素
System.out.println(set.contains("香蕉"));
// 迭代器遍历
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// 清空集合
set.clear();
System.out.println();
// 判断是否为空
System.out.println(set.isEmpty());
HashSet
HashSet:
- Set接口常用的实现类之一
- HashSet底层是一个HashMap使用的是HashMap中的Key
- 无序 非线程安全 不可重复 可为null
HashSet存储过程:
存储结构:哈希表(数组+链表+红黑树)
- 根据HashCode计算元素存放位置如果此位置为空,则直接保存,否则执行equals方法,如果equals方法为true,则认为是重复的,否则形成链表
HashSet<String> hashSet = new HashSet<>();
// 添加 add()
hashSet.add("香蕉");
hashSet.add("葡萄");
hashSet.add("西瓜");
// toString()
System.out.println(hashSet.toString());
// 删除 remove()
hashSet.remove("葡萄");
System.out.println(hashSet.toString());
// 获取长度 size()
System.out.println(hashSet.size());
// 判断是否为空 isEmpty()
System.out.println(hashSet.isEmpty());
// 判断是否包含某个值 contains()
System.out.println(hashSet.contains("西瓜"));
// 迭代器 遍历 iterator()
Iterator<String> iterator = hashSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// 增强for
for (String s : hashSet) {
System.out.println(s);
}
TreeSet
TreeSet:(红黑树)
- 一个有序的(按照我们自己指定的比较规则升序顺序)Set集合底层是一个TreeMap
- 要求TreeSet中的元素必须实现Comparable接口,重写CompareTo方法如果方法返回值为0就认定为重复元素
// TreeSet 红黑树
// 操作基本数据类型
TreeSet<String> treeSet = new TreeSet<>();
// add() 添加
treeSet.add("苹果");
treeSet.add("香蕉");
treeSet.add("橘子");
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
// remove() 删除
treeSet.remove("橘子");
// contains() 判断是否包含某个元素
System.out.println(treeSet.contains("香蕉"));
// 判断是否为空
System.out.println(treeSet.isEmpty());
// 遍历 增强for
for (String s : treeSet) {
System.out.println(s);
}
// 迭代器遍历
Iterator<String> iterator = treeSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// 操作类 必须实现Comparable 重写CompareTo方法
public class TreeSets {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<>();
Person p1 = new Person("塞罗",10);
Person p2 = new Person("贝利亚",20);
Person p3 = new Person("奥特之王",30);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
// 删除
treeSet.remove(p1);
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
}
}
public class Person implements Comparable<Person> {
......
// 重写compareTo方法 指定比较规则
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.name);
int n2 = this.age - o.getAge();
return n1 == 0 ? n2 : n1;
}
}
/*
* TreeSet
* Comparator(): 实现定制比较(比较器)
* Comparable : 可比较的
* */
TreeSet<Person> treeSet = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getName().compareTo(o2.toString());
int n2 = o1.getAge() - o2.getAge();
return n1 == 0 ? n2 : n1 ;
}
});
Person p1 = new Person("塞罗",10);
Person p2 = new Person("贝利亚",20);
Person p3 = new Person("奥特之王",30);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
LinkedHashSet
LinkedHashSet 可以保证元素的顺序 插入顺序
- 不能重复 唯一 可为null
- 线程不安全
- 可以保证顺序
- 底层依然是一个HashSet而HashSet底层就是HashMap
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(10);
linkedList.add(20);
linkedList.add(30);
linkedList.add(40);
// 查看是否包含某个元素
System.out.println(linkedList.contains(10));
// 根据下标获取元素
System.out.println(linkedList.get(2));
System.out.println(linkedList.toString());
// 删除第一个元素
linkedList.removeFirst();
// 删除最后一个元素
linkedList.removeLast();
System.out.println(linkedList.toString());
// 添加到第一个元素
linkedList.addFirst(0);
// 添加到最后一个元素
linkedList.addLast(100);
System.out.println(linkedList.toString());
// 根据值查询下标
System.out.println(linkedList.indexOf(30));
// 遍历
for (Integer integer : linkedList) {
System.out.println(integer);
}
// iterator
Iterator<Integer> iterator = linkedList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Map接口
Map特点:
- 存储一对数据(Key–Value)
- 键 :无序,无下标,不可重复 (唯一)
- 值 :无序,无下标,允许重复
HashMap
Map接口的实现类
- HashMap集合
- 无序
- 键和值都允许为null
- 值可以重复
- 键不可以重复,也就是说只能有一个键为null 重复对已经存在的键设置值 将覆盖原来值
- 初始的数组长度是16 负载因子是0.75 表示数组的使用达到75%将扩容
- HashMap刚创建时,table是null,为了节省空间,当添加了第一个元素,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍,目的是减少调整元素的个数。
- JDK1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的是提高执行效率。
- JDK1.8 当链表长度小于6时,调整成链表
- JDK1.8 以前,链表时头插入,JDK1.8以后时是尾插入
方法 | 描述 |
---|---|
put() | 添加 |
keySet() | 获取所有的键 |
keyValue() | 获取所有的值 |
Map<Integer,String> hashMap = new HashMap<>();
// 添加 put()
hashMap.put(1,"迪迦");
hashMap.put(2,"梦比优斯");
hashMap.put(3,"高斯");
hashMap.put(4,"戴拿");
System.out.println(hashMap.toString());
// 删除 remove()
hashMap.remove(4);
System.out.println(hashMap.toString());
System.err.println("-----------------------遍历----------------------");
// 方式1. 获取所有的键
Set<Integer> keySet = hashMap.keySet();
for(Integer key : keySet){
System.out.println("键是:" + key + "值是:" + hashMap.get(key));
}
System.err.println("---------------------------------------------");
// 方式2 获取所有的值
Collection<String> values = hashMap.values();
for(String value : values){
System.out.println("值是:" + value);
}
// 方式3 获取键值对组合
Set<Map.Entry<Integer,String>> entrySet = hashMap.entrySet();
for(Map.Entry<Integer,String> en : entrySet){
System.out.println(en.getKey() + en.getValue());
}
// 方式4 获取键值对组合迭代器
Iterator<Map.Entry<Integer,String>> iterator = hashMap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Integer,String> next = iterator.next();
System.out.println(next.getKey());
System.out.println(next.getValue());
}
HashTable
HashTable和HashMap有相同的API
- 线程安全的
- 初始容量为11数组
- 扩容是两倍+1 rehash();
Hashtable<Integer,String> hashtable = new Hashtable<>();
hashtable.put(1,"泰罗");
hashtable.put(2,"迪迦");
hashtable.put(3,"戴拿");
hashtable.put(4,"塞罗");
System.out.println(hashtable.size());
System.out.println(hashtable.toString());
hashtable.remove(1);
// 替换
hashtable.replace(2,"奥特之父");
System.out.println(hashtable.get(3));
System.out.println("------------遍历-------------");
// 获取所有的key
Set<Integer> keySet = hashtable.keySet();
for (Integer key : keySet) {
System.out.println(key + hashtable.get(key));
}
System.out.println("-------------------------");
// 获取所有的value
Collection<String> values = hashtable.values();
for (String value : values) {
System.out.println(value);
}
System.out.println("-------------------------");
// 获取Entry每一项
Set<Map.Entry<Integer, String>> entry = hashtable.entrySet();
for (Map.Entry<Integer, String> en : entry) {
System.out.println(en.getKey() + ":" + en.getValue());
}
System.out.println("-------------------------");
// 获取Entry迭代器
Iterator<Map.Entry<Integer, String>> it = hashtable.entrySet().iterator();
while(it.hasNext()){
System.out.println(it.next());
}
TreeMap
TreeMap:可以排序的Map集合
- 顺序是按照比较器比较的升序
- 要求TreeMap中的键必须实现Comparable接口 重写 comparaTo方法
- 有序的
- 线程安全的
TreeMap<String,String> treeMap = new TreeMap<>();
treeMap.put("1","哈");
treeMap.put("2","嘿");
treeMap.put("3","嘻");
Set<Map.Entry<String, String>> entry = treeMap.entrySet();
for (Map.Entry<String, String> en : entry) {
System.out.println(en.getKey() + ":" + en.getValue());
}
TreeMap<Person,String> tm = new TreeMap<>();
tm.put(new Person("哈哈",10),"hahahaa");
tm.put(new Person("嘿嘿",10),"heiheih");
tm.put(new Person("嘻嘻",10),"xixixix");
Set<Map.Entry<Person, String>> etm = tm.entrySet();
for (Map.Entry<Person,String> en : etm) {
System.out.println(en.toString());
}
Properties
Properties也是Map集合的实现类
此类用于记录配置文件信息,所以只可以存储键和值均为字符串,所以不能使用put方法添加元素,必须使用setProperty()方法
Properties properties = System.getProperties();
properties.list(System.out);
System.out.println("----------------------");
System.getProperties();
// 获取jdk版本号
System.out.println(properties.get("java.version"));
System.out.println("----------------------");
Properties p = new Properties();
p.setProperty("a","a");
p.setProperty("b","b");
p.setProperty("1","c");
p.setProperty("2","d");
Collections工具类
Collections 工具类 提供了用于操作集合的方法
- max() 最大值
- min() 最小值
- binarySearch() 二分查找,要求必须先排序
- sort()排序 升序
List<Integer> list = new ArrayList<Integer>();
list.add(60);
list.add(30);
list.add(20);
list.add(90);
// 最大值
System.out.println("最大值:" +Collections.max(list));
// 最小值
System.out.println("最小值:" + Collections.min(list));
// 排序
System.out.println("排序前" + list.toString());
Collections.sort(list);
System.out.println("排序后" + list.toString());