今天书生带来关于java集合的文章
首先:关于Java的集合,什么是集合?
1、集合类存放于java.util包中。
2、集合类型主要有3种:set(集)、list(列表)和map(映射)。
3、集合存放的都是对象的引用,而非对象本身。所以我们称集合中的对象就是集合中对象的引用。
简单来讲:集合就是一个放数据的容器,准确的说是放数据对象引用的容器。
有几个要注意的点:
①集合只能存放对象。比如你存入一个int型数据66放入集合中,其实它是自动转换成Integer类后存入的,Java中每一种基本数据类型都有对应的引用类型。
②集合存放的都是对象的引用,而非对象本身。所以我们称集合中的对象就是集合中对象的引用。对象本身还是放在堆内存中。
③集合可以存放不同类型,不限数量的数据类型。
再了解一下它的框架体系:
总的来说,集合是可分为三大体系:Set,List,Map,其中Set是无序的,不可重复的;List是有序的,可重复的;Map则是key-value具有映射关系的集合。
首先,整个框架体系的基础支撑,是Iterator(迭代器),迭代器是一种设计模式,是一个对象,可用于遍历元素,元素被访问的顺序取决于集合的实现类,在java中Iterator功能较为简单且是单向的。
但凡实现了 Iterable 接口的类都支持使用 for each 语句循环,因此标准集合类库都允许使用 for each 语句循环。在实现了 Iterable 接口的类中,iterator 方法用于迭代器;forEach 方法可以使用 lambda 表达式逐个处理元素;spliterator 方法用于创建一个可分割迭代器,以支持并行遍历。
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
再说为List设计的ListIterator,Java 以双向链表的形式实现 List。它可以从两个方向遍历List,也可以从List中插入和删除元素。而双向链表相比数组有这些特点:在指定位置插入元素时,数组需要移动该位置后的元素,双向链表不需要;删除元素时也相同。因为是双向链表,ListIterator 支持反向遍历元素。
①hasNext 判断集合中是否还有剩余的元素
②next 逐个访问元素
③hasPrevious 判断集合中是否还有打头的元素
④previous 反向逐个访问元素
⑤remove 基于遍历的方向删除元素
⑥set(e) 修改当前访问的元素
⑦add(e) 基于当前访问的元素位置插入元素
接着说Collection,Collection 和 Iterator 都是泛型接口,内含操作任意集合的实用方法。为了实现 Collection 接口的方便,java.util 提供了 AbstractCollection 抽象类,以抽象常见的处理逻辑。AbstractCollection 抽象类实现了 finishToArray, hugeCapacity 方法可用于辅助扩容。
再说Conllection下的Set,List
Set:
1) Set 集合属于单列集合,不允许包含重复元素;
2) 判断元素是否重复的标准为对象的 equals 方法,存在时返回 false,不存在返回 true;
3) 元素的排序规则,由相应的实现类决定,分为无序、元素大小排序、写入顺序排序;
Set实现类:HashSet,TreeSet以及LinkedHashSet
HashSet:它是按照哈希算法来存储集合中的元素,所以具有很好的存储和查找性能。它有这些特点: 不能保证元素的存放顺序,不可重复,不是线程安全的,集合元素可以使用null。当向HashSet集合存放一个元素时,HashSet会调用该对象的hashcode()方法得到该对象的hashcode值,根据这个值决定它在HashSet中的存储位置。 如果两个的对象的equals()方法返回true,但hashcode()返回值不相等,hashset会把他们存放在不同的位置,但是仍然可添加成功。存放位置由hashcode决定。
(1) HashSet 实现了 Set 接口,继承了 AbstractSet 类,由哈希表支持,看源码可以发现是一个 HashMap 实例。
(2) HashSet 不保证集合内元素的迭代顺序,特别是不保证迭代顺序永久不变,该集合运行 null 元素存在。
(3) HashSet 中的元素,作为 HashMap 键值对的 Key 存储,而 Value 由一个统一的值保存。
(4) HashSet 默认初始化大小为 16,扩容加载因子为 0.75,扩容大小为原来的一倍。即一个初始化size为16的
(5) HashSet,元素添加到12个的时候会进行扩容,扩容后的大小为32。
TreeSet:可以确保元素处于排序状态,是SortedSet接口的实现类。支持自然排序和定制排序,默认使用自然排序。会调用元素的compareTo( )方法比较大小,实现排序。TreeSet必须放入同样类的对象(默认会进行排序),否则会出现类型转换异常,可以用泛型来限制。Set的无序是指放入顺序和取出顺序不一致,TreeSet有序是指给里面的元素进行了排序。两个概念不一样。
(1) TreeSet 实现了 NavigableSet 接口,继承了AbstractSet类,由哈希表支持,看源码可以发现是一个 TreeMap 实例。
(2) TreeSet 中的元素有序的,排序规则遵照元素本身的大小进行排序,元素不能重复。
(3) TreeSet 中的元素,作为 TreeMap 键值对的 Key 存储,而 Value 由一个统一的值保存。
LinkedHashSet:
(1) LinkedHashSet实现了 Set 接口,继承了HashSet类,由哈希表支持,看源码可以发现是一个LinkedHashMap 实例。
(2) LinkedHashSet中的元素有序的,排序规则遵照元素写入顺序进行排序,元素不能重复。
(3) LinkedHashSet 中的元素,作为 LinkedHashMap 键值对的 Key 存储,而 Value 由一个统一的值保存。
List:
1) List 集合属于单列、有序的、允许元素重复、可以为 null 的集合;
2) List 接口的实现类主要有三种:ArrayList、LinkedList、Vector。
List允许使用重复元素,可以通过索引来访问指定位置的集合元素。默认按添加顺序设置元素的索引。
Collection接口—(extends)—>List接口—(implement)—>ArrayList类
ArrayList:
(1) ArrayList 实现了 List 接口,继承了 AbstractList 类,由一个 Object[] 实例实现,即底层为数组结构;
(2) 默认初始化长度为 10,扩容规则为 0.5倍的原容量加1,即一次扩容后的长度为 16;
(3) 特点:查询速度快,添加、删除相对于LinkedList较慢、线程不同步(不安全)。
LinkedList:
(1) LinkedList 实现了 List 接口,继承了 AbstractSequentialList 类,由一个 Node 节点链表实现,即底层为链表结构;
(2) 由于LinkedList 数据结构为链表,无预扩容机制;
(3) 特点:添加、删除速度快,查询相对于ArrayList较慢、线程不同步(不安全)。
Vector:
(1) Vector实现了 List 接口,继承了 AbstractList 类,由一个 Object[] 实例实现,即底层为数组结构;
(2) 默认初始化长度为 10,扩容加载因子为 1,当元素长度大于原容量时进行扩容,默认为 10,一次扩容后容量为 20;
(3) 特点:线程安全,但是速度慢;在实现的方法上,用 synchronized 关键字进行了修饰,即在方法上实现了同步锁。
框架体系图左边刨析完了,再说右边的Map、HashMap、TreeMap、LinkedHashMap
Map:Map映射是符号表的一种,用于储存和操纵键值对。
(1) Map 集合属于双列Key-value键值对的集合,Key不允许重复,是否允许为 null 根据实现类而定,Value 随意;
(2) Map 接口的实现类主要有三种:HashMap、LinkedHashMap、TreeMap
HashMap:
(1) HashMap实现了 Map接口,继承了 AbstractMap类,数据结构采用的位桶数组,底层采用链表或红黑树进行存储;
(2) 默认初始化长度为 16,扩容加载因子为 0.75,一旦大于 0.75*16之后,就会调用resize()进行扩容,扩容2倍,即32;
(3) JDK1.7中,数据结构采用:位桶数组+链表结构;JDK1.8中,数据结构采用:位桶数组+(链表/红黑树);
(4) 支持克隆,无序,线程不同步,非线程安全。
TreeMap:
(1) TreeMap实现了 NavigableMap接口,继承了 AbstractMap 类;
(2) 数据结构基于红黑树实现;
(3) 该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法;
(4) 无初始化长度;
(5) 支持克隆,有序,线程不同步,非线程安全。
LinkedHashMap:
(1) LinkedHashMap 实现了 Map 接口,继承了 HashMap 类。
(2) 迭代顺序由 accessOrder 属性的决定,默认为 false,以插入顺序访问;设置为 true 则按上次读取顺序访问(每次访问元素时会把元素移动到链表末尾方便下次访问,结构会时刻变化)。
(3) 默认初始化长度为 16,扩容加载因子为 0.75,一旦>0.75*16之后,就会调用resize()进行扩容,与HashMap一致;
(4) 支持克隆,有序,线程不同步,非安全。
好了,本文到此结束,希望对大家有所帮助。