Java集合是什么?

今天书生带来关于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设计的ListIteratorJava 以双向链表的形式实现 List。它可以从两个方向遍历List,也可以从List中插入和删除元素。而双向链表相比数组有这些特点:在指定位置插入元素时,数组需要移动该位置后的元素,双向链表不需要;删除元素时也相同。因为是双向链表,ListIterator 支持反向遍历元素。

①hasNext 判断集合中是否还有剩余的元素

②next 逐个访问元素

③hasPrevious 判断集合中是否还有打头的元素

④previous 反向逐个访问元素

⑤remove 基于遍历的方向删除元素

⑥set(e) 修改当前访问的元素

⑦add(e) 基于当前访问的元素位置插入元素

Java集合 - 知乎

接着说Collection,Collection 和 Iterator 都是泛型接口,内含操作任意集合的实用方法。为了实现 Collection 接口的方便,java.util 提供了 AbstractCollection 抽象类,以抽象常见的处理逻辑。AbstractCollection 抽象类实现了 finishToArray, hugeCapacity 方法可用于辅助扩容。

再说Conllection下的Set,List

Set:

1) Set 集合属于单列集合,不允许包含重复元素;

2) 判断元素是否重复的标准为对象的 equals 方法,存在时返回 false,不存在返回 true;

3) 元素的排序规则,由相应的实现类决定,分为无序、元素大小排序、写入顺序排序;

Set实现类:HashSetTreeSet以及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 接口的实现类主要有三种:ArrayListLinkedListVector

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) 支持克隆,有序,线程不同步,非安全。

好了,本文到此结束,希望对大家有所帮助。

参考文章:https://zhuanlan.zhihu.com/p/65503038

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值