HJava集合
集合结构
Collection接口
- List接口(线性表)
- ArrayList(顺序表) 线程不安全 效率高
- LinkedList(链表)双向链表
- Vector 比较古老 线程安全
- set接口(数学中的集合)
- HashSet
- LinkedHashSet
- TreeSet
Map接口
- HashMap
- LinkedHashMap
- HashTable
- Properties
- SortedMap
- TreeMap
Collection接口中的抽象方法(注意如果想准确无误的使用功能要重写equals方法,在java中有些数据结构方法需要按值操作,而按值操作就设计到比较值,equals默认比较地址,需要重写符合现实规律)
添加元素
add(E e)//添加元素
addAll(Collection c)//添加另外一个集合中的元素
删除
remove(E e)//删除单个元素 需要重写equals方法不然按地址确认
removeAll(Collection c)删除另外一个集合中的元素
clear()//清空集合中的元素
判断
contains(E e) //判断元素是否在该集合中
containsAll(Collection coll)//判断是否为子集
equals(Collection c)//判断两个集合是否相等
数学运算
retainAll(Collection c)
获取属性
size()//返回集合的本身长度
iterator()//返回集合的迭代器
转换操作
Object toArray()//将集合转成数组
迭代器
iterator接口常用方法
hasNext()//判断下一个指针位置是否有数据
next()//把指针向后移动一位,然后取出数据
remove()//删除迭代器当前指针指向位置的元素
List接口
ArrayList实现类(如果是查找多就用这个,插入删除会移动大量元素不建议使用)
源码分析;
在jdk7.0中Arraylist底层采用Object数组如果采用无参构造器是默认初始化10个容量长度
如果东西装满了扩容的话是扩容1.5倍
jdk8中的区别是一开始不会初始化底层的Object数组,而是在第一次add操作时才会构造数组//延迟数组创建,节省内存
结论:
使用指定容量的构造器避免扩容带来的效率低下
LinkedList
底层采用双向链表,如果插入删除多就用这个,因为查找要一个一个找过去,不想ArrayList可以根据索引
Vector(基本不用,如果遇到多线程会会使用Collections工具类下的方法获取线程安全的集合)
源码分析:
底层:线程安全的,方法都被加了sychronized,不管是jdk7还是8都是调无参构造会默认使用10个容量初始化的对象,扩容是安装2倍
List接口定义方法:(因为list接口表示元素是有位序的,所以在list里面的定义的方法都是按位操作的方法)
增
add(int index,E e) //新增数据到指定位序
addAll(int index,Collection c)//将指定集合中的数据添加到指定位序
查
get(int index)//获取指定位序的值
indexof(E e)//获取指定元素首次出现的位置
lastIndexof(E e)//获取指定元素最后一次出现的位序
删
remove(int index)//将元素从指定位序上移除并且返回
改
set(int index,E e)//修改指定位序的元素
截取子串
subsring(int fromindex,int end index)//截取左闭右开区间的子串
set接口
set接口没有新增方法,因为set是无序的也就是元素在物理地址上是没有位序的
无序性
set集合内部存储元素是采用哈希表(解决冲突的方法还是采用的链地址法的方式)而不是顺序表的方方法,所以set集合元素不能通过位序去访问
不可重复性
set集合添加元素时会先调用hashcode()方法计算出在哈希表中的存放位置,如果发生hash冲突这个时候在比较equals方法如果说equals方法返回为true则不添加,否则添加到冲突位置里面的链表中
hashcode和equals重写原则:
原则一:一个对象多次调用hashcode返回结果都应该一致
原则二:hashcode和equals应该保持一致性如果equals为true那么hashcode返回结果应该也是一致的
原则三:在equals中用于比较的值在hashcode应该都要用上
linkedHashSet
他是hashset的子类,继承于hashset,和hashset不一样的是它的内部维护了两个引用,如果经常遍历的话就要使用LinkedHashSet
TreeSet
TreeSet内部 采用红黑树,元素是有序的,排序过程是依赖Compareable接口
定制排序就是在创建TreeSet对象的时候在内部传入Comparetor的构造器
Map接口
HashMap底层原理类似于HashSet是线程不安全的 JDK7.0值钱hashmap采用哈希表+链表的形式
JDK8.0HashMap采用哈希表+链表+红黑树
LinkedHashMap是HashMap的子类,和哈希表的不同是加了前后的引用遍历会更快,如果需要频繁遍历的话可以使用LinkedHashMap
TreeMap的底层结构是红黑树,结构类似于TreeSet
HashTable 底层是线程安全的,实现结构类似于HashMap,但是不考虑使用,如果需要线程安全的话会用Collections里面的方法来获取线程安全的map集合
Properties 它的键值都是Sting类型,他是专门用来读取配置文件的
Map接口中的键是无序 不可重复的当我们去存数据的时候,内部会将Key和value封装成entry对象
HashMap的底层原理:
jdk7:首次创建HashMap就会创建长度16的Entry数组 先会调用key的hashcode方法,然后根据hashcode使用某种算法找到对应entry数组的位置,如果对应位置没有数据就直接放入,如果存在比较hashcode值是否相等,除了hashcode和equals全部相等情况会覆盖其他都是插入
扩容的比例是两倍
jdk8.0实现的方式
不采用Entry数组而是采用node数组
和ArrayListjdk8.0类似只有首次调用put方法的时候才会构建长度16数组,并且当某个所以位置链长度超过8数组长度超过64的话此索引位置数据就会改用红黑树来存储
Map接口常用方法
增加:
put(K k,V v);//存放数据
putAll(Map m)//将另外一个map集合中的数据放入map中
删除
remove(Key k)//删除键值对并且返回
clear()//清空数据
判断
containsKey(Object key)//判断键是否存在
containsValue(Object value)//判断值是否存在
isEmpty()//判断集合是否为空
修改:
put(K k,V v)//修改数据
遍历:
keySet()//返回key的set集合
entrySet()//返回键值对的set集合
values()//返回values的Collection集合
size()//返回长度
Properties类 //用来读取配置文件的 它的键和值都是字符串
load(InputStream is)//加载配置文件的流
getProperty(String key)//获取值 字符串
集合工具类Collections
常用方法
reverse(List list)//反转集合
shuffle(List list)//给集合数据随机排序
sort(List list)//自然排序
sort(List list,Compartor com)//定制排序
Max(Collection c)//自然排序找集合中最大的元素
Max(Collection c,Compartor com)//定制排序找集合中最大的元素
Min(Collection c)//自然排序找集合中最小的元素
Min(Collection c,Compartor com)//定制排序找集合中最小的元素
frenquence(Collection c,Object obj)//找集合中指定元素出现的次数
copy(List dest,List src)//拷贝集合不过需要拷贝到集合中的数据不小于原集合中的数据