java集合——数组列表(ArrayList)+散列集(HashSet)

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java集合——数组列表(ArrayList)+散列集(HashSet) 的相关知识;
0.2) 散列集HashSet 涉及到 hashCode()方法 和 hash 码, 详情参见: http://blog.csdn.net/pacosonswjtu/article/details/50312917
0.3) for full source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/chapter13/SetTest.java


【1】数组列表(ArrayList)

1.1) List接口用于描述一个有序集合, 并且集合中每个元素的位置十分重要;
1.2)有两种访问元素 的协议:

  • 1.2.1)一种是用迭代器;
  • 1.2.2)另一种是使用 get 和 set方法随机的访问每个元素;
  • 1.2.3)后者不适用于链表, 但对数组却很有用。集合类库提供了一种大家熟悉的ArrayList 类, 这个类也实现了 List接口。

1.3) ArrayList 封装了一个动态再分配的对象数组;

Annotation)

  • A1)对于有经验的 coder 来说, 在需要动态数组的时候, 可能会使用 Vector类;
  • A2)为什么要用 ArrayList 取代 Vector呢? 因为, Vector 类的所有方法都是同步的(可以由两个线程安全的访问一个 Vector对象);但是, 如果由一个线程访问 Vector, 代码需要在同步操作上 耗费大量的时间;(干货——ArrayList非同步访问,而Vector同步访问)
  • A3)而ArryaList 不是同步 的, 所以, 建议在不需要同步时 使用 ArrayList, 而不要使用 Vector;
    这里写图片描述

【2】散列集(HashSet)

2.1)如果不在意元素的顺序,可以有几种能够快速查找元素的数据结构。 其缺点是无法控制元素出现的次序。 它们将按照有利于其操作目的的原则组织数据;
2.2)散列表定义: 有一种众所周知的数据结构, 可以快速查找所需要的对象;

  • 2.2.1)散列码:散列表为每个对象计算一个整数, 称为散列码;
  • 2.2.2)散列码是由对象的实例域产生 的一个整数。 更准确的说, 具有不同数据域的对象将产生不同的散列码, 下表列出了几个散列码的实例, 它们是由String 类 的hashCode 方法产生的;
    这里写图片描述
    2.3)如果自定义类, 就要负责实现这个类 的 hashCode 方法。
    Attention)

  • A1)自己实现的 hashCode方法要与 equals 方法兼容, 即 如果a.equals(b) 为 true, a 与b 必须具有相同的散列码;(干货, 两个对象的equals 方法结果===它们的 hashCode 方法的结果)

  • A2)现在, 最重要的问题是 散列码要能够快速计算出来, 并且这个计算只与要散列 的对象状态有关, 与散列表的其他对象无关;

2.4)在java中, 散列表用链表数组实现: (C语言应该讲过链表数组,我们不累述)

  • 2.4.1)每个列表就被称为桶: 要想找到表中对象 的位置, 就要先计算它的散列码, 然后与桶的总数取余, 所得到的结果就是保存这个元素的桶的索引;
    这里写图片描述
  • 2.4.2)如何设置桶数?
    • 2.4.2.1) 通常,将桶数设置为预计元素个数的 75%~150%;有些研究人员认为:尽管没有确凿的证据, 但最好还是将桶数设置为一个素数, 以防止键的集聚;
    • 2.4.2.2)标准类库使用的桶数是2的幂,默认值为16;(为表大小提供的任何值都将被自动转换为2的下一个幂);
  • 2.4.3)再散列:如果散列表太满, 就需要再散列;如果要对散列表再散列, 就需要创建一个桶数更多的表,并将所有元素插入到这个新表中, 丢弃原来的表;
    • 2.4.3.1)装填因子: 它决定何时对散列表进行再散列, 一般设置为 0.75;

2.5)散列表可以用于实现几个重要的数据结构:

  • 2.5.1)其中最简单的是 set类型。 set是没有重复元素的集合。set 的 add 方法首先在 集中查找要添加的元素, 如果不存在,就将这个对象添加进去; (干货——add方法的执行原理)

2.6)java 集合提供了 一个 HashSet类, 它实现了基于 散列表的集;可以用 add 方法添加元素,还有contains 方法被重新定义, 用来快速查看是否某个元素已经出现在集合中了;

  • 2.6.1)散列集迭代器将依次访问所有的桶。 由于散列将元素分散到表的各个位置上, 所以访问他们的顺序几乎是随机的。 只有不关心集合中元素顺序的时候才应该使用 HashSet (干货)
  • 2.6.2)看个荔枝: 这个程序将读取输入的所有单词, 并且将它们添加到散列集中。 然后遍历散列集中的不同单词, 最后打印出单词数量;

Warning)在更改集中元素的时候要格外小心。 因为如果元素的散列码发生了改变, 元素在数据结构中的位置也会发生相应变化的;
这里写图片描述
这里写图片描述
这里写图片描述

API java.util.HashSet<E> 1.2
HashSet() :构造一个空散列集;
HashSet(Collection< ? extends E> elements) :构造一个空散列集, 并将集合中的元素添加到这个散列集中;
HashSet(int initialCapacity)::构造一个空散列集;且具有执行容量(桶数)
HashSet(int initialCapacity, float loadFactor):构造一个具有指定容量和装填因子(0.0~1.0)的空散列集;

API java.lang.Object 1.0
int hashCode() : 返回这个对象的散列码。散列码可以是任何整数(正负数)。equals 和 hashCode 的定义必须兼容, 即 如果 x.equals(y) 为true, x.hashCode()必须等于 y.hashCode();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值