Java的集合框架:
- Collection接口:
List:里面存放的数据是有序的,并且数据是可重复的
- ArrayList:动态数组,顺序存储,遍历、添加(添加到末尾,非插入)效率较高
- LinkedList:链式结构,插入、删除效率高,遍历查找效率低
- Vector:动态数组,比较老的集合结构,一般很少使用
Set:里面的数据是无序的,不可重复的
HashSet:主要的实现类,无序不代表随机
LinkedHashSet : 是在原有的基础上底层通过一个链表进行维护,遍历效率会有提升
若经常对set进行遍历操作,可以采用LinkedHashSet
TreeSet:TreeSet中存放的数据可以进行排序(Comparable Comparator)
TreeSet中存放的对象必须实现Comparable
TreeSet中是不能存放空对象的 !!!
- Map接口:Map中存放的数据都是一对一对的,里面有一个叫做key,另外一个叫做value,键值对
- HashMap:主要实现类,map中数据也是无序的,线程不安全,但是效率高
- TreeMap:可以排序的
- HashTable:比较老的一个,很少用,线程安全的,但是效率较低
- Properties类 property(属性)
Collection接口
1 | Collection<String> coll = new ArrayList<>(); |
List
ArrayList
ArrayList:动态数组,底层是由数组实现数据存储的
对于数据基本操作:
- 增:add()
- 删:remove(object) remove(index)
- 改:set(index,element)
- 查:get(index)
- 插入:add(index,element)
- 遍历:迭代器(next()、hasNext())、for、foreach
新增的:
- add(index,element)
- remove(index)
- set(index,element)
- get(index)
- subList(startIndex,endIndex)
- indexOf(object)
- sort(Comparator) // 排序
1 | // 创建ArrayList对象 |
ArrayList遍历方式:
1 | // 1、迭代器 |
注意点:遍历时要删除元素,采用迭代器形式,不要用foreach会报错
1 | // 1、迭代器(可以的) |
排序:
1 | // 对集合中元素进行排序,需要传入一个Comparator接口的对象 |
LinkedList
LinkedList里面的常规增删改查方法与ArrayList一样
1 | LinkedList<String> list = new LinkedList<>(); |
Vector
1 | Vector<String> vector = new Vector<>(); |
三者区别
1.ArrayList
- 创建ArrayList时,内部会生成一个空数组
- 第一次添加时,数组长度为10
- 后期数组满了后在扩容时,是扩容1.5倍
- 线程不安全,效率高
2.Vector
- 创建时立马生成长度为10的数组
- 扩容时默认以2倍扩容
- 线程安全,但是带来副作用就是效率低
3.LinkedList
- 链式存储结构,双链表
- 通过Node类表示数据结点,
- 里面item属性用来保存具体的数据
undefinednext属性保存下一个结点地址
undefinedprev属性保存上一个结点地址
- 里面item属性用来保存具体的数据
Set
HashSet
Set底层由数组+链表实现
- 1.数据存放在数组中(数组的初始容量为16)
- 2.无序性是根据存放对象的哈希值经过某个算法(散列算法)算出在数组中存放的位置,从而导致存放的数据不太可能连着存放,展现出来一种无序状态
- 3.数据的不可重复需要:数据对象对hashcode().eauals()进行重写才能体现,否则还是可以添加重复的数据,经过hashcode()得到的哈希值算出存储的位置后:
若数组当前位置没有数据,就直接放进去
- 若数组当前位置有数据,就通过对象的equals()进行判断,
* 若相等则不添加,
* 若不相等,则以链表的形式拼接在原有数据下面;
1 | HashSet<String> set = new HashSet<>(); |
TreeSet
1 | // TreeSet中是不能存放空对象的 !!! |
Map接口
###HashMap原理简要认识:
- HashMap<String, String> map = new HashMap<>();
- 底层由 数组+链表+红黑树
- 创建HashMap时,内部存放键值对数据的数组table,没有初始化,只是初始化了一个加载因子为0.75
- 加载因子:可以认为数组中元素个数达到当前数组长度的百分比后进行扩容一个参数
- 当第一次添加数据时,会把table这个数组初始化,长度为16
- 后续再去添加元素时,如果数组中元素的个数 = 数组长度*加载因子,那么就会进行扩容,扩容为原来的2倍
- 当数组长度大于64,并且数组中某个元素对应的链表长度大于8时,就会采用红黑树(二叉树)进行存储,提高查找的效率
1 | /* |
HashMap
1 | // 第一个指定key的类型,第二个指定value的类型 |
map的遍历:
1 | // 方式1:获取key的set集合,然后遍历该集合获取map中的所有数据 |
1 | // 方式2: |
1 | // 方式3: |
CurrentHashMap
由于HashMap是线程不同步的,虽然处理数据的效率高,但是在多线程的情况下存在着安全问题,因此设计了CurrentHashMap来解决多线程安全问题。
JDK1.8的实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap,虽然在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本.
HashMap和ConcurrentHashMap的知识总结
TreeMap
TreeMap中是按照key进行一个自然排序,要求key所对应的数据必须实现Comparable接口
1 | TreeMap<Hero, String> treeMap = new TreeMap<>(); |
1 | // 通过在构造方法中传入Comparator对象自定义比较规则, |
Properties
Properties:可以用来读取(加载)项目中的配置文件(例如:数据库的连接信息,用户名 密码 …)
创建配置文件(xxx.properties):右键单击项目名 -> new -> file
- 井号代表注释
- 内容格式:属性名=属性值 / 属性名:属性值
1 | // 创建Properties对象 |
总结
1、Collection 和 Collections
Collection是一个接口,是所有单值集合的父接口;
Collections是一个帮助类,这个类中提供了很多对于集合操作的静态方法
2、List接口 和 Set接口的区别
List接口和set接口都是Collection接口的子接口
List接口中的元素是有序可重复的;
Set接口中的元素是无序不可重复的;
3、ArrayList 和 LinkedList的区别
ArrayList和LinkedList集合都是List接口的实现类,其元素都是有序可重复的;
ArrayList中元素的存储是基于数组的实现,元素查询、添加速度比较快,插入元素速度较慢;
LinkedList中的元素是基于链表的实现,元素的插入速度较快;
4、ArrayList 和 Verctor的区别
ArrayList和Verctor都是基于数组的实现;
ArrayList是线程非安全的,但是ArrayList的存储效率比较高;
Verctor是线程安全的;
5、HashSet和TreeSet的区别
两者都是Set接口的实现类,其元素都是无序不可重复的;
区别是存储方式不同:
HashSet是基于hash码散列存储
TreeSet是树形存储
6、HashMap和HashTable的区别
两者都是基于Map接口的实现类,都表示键值对集合。
HashMap中运行一个null键和多个null值;但Hashtable中不允许使用null作为key和value;
HashMap未实现同步,是线程非安全的;Hashtable实现了同步是线程安全的;