集合类的笔记

集合有两个基本接口:Collection和Map
Collection下分为:List、Set、Queue

1、链表是一个有序集合,添加元素的时候都是加在了链表的尾部,如果要在链表的中间添加元素可以利用ListIterator。只是对自然有序的集合使用迭代器添加元素才有意义,例如Set这种集合的元素完全无序,就没有任何实际意义。所以在Iterator接口中就没有add方法,集合类库的子接口:ListIterator包含add()方法。但是与Collection.add不同,这个方法不返回boolean类型的值,,它假定操作总会改变链表。
在这里插入图片描述
在这里插入图片描述
添加后的list:
在这里插入图片描述
这里值得注意的是:调用previous()后再调用remove()方法删除的是迭代器所在位置的右侧的元素。

数组和数组列表有一个重大的缺陷就是从数组的中间位置删除一个元素要付出很大的代价,因为数组中被删除元素之后的所有元素都要向数组的前端移动,在数组中插入一个元素也是这样。链表(linked list)很好的解决了这个问题,尽管数组在连续的存储位置上存放对象的引用,但链表却将每个对象存放在独立的节点中,每个节点还存放着下一个结点的引用。在java程序设计语言中,所有的链表都是双向链接,每个结点还保存着前一个结点的引用。

2、数组链表,在需要动态数组的时候很多人都会选择Vector类,为什么要用ArrayList取代Vector呢?Vector类的所有方法都是同步的,可以有两个线程安全的访问一个Vector对象,但是如果只有一个线程访问Vector,代码再同步上操作耗费大量的时间。这种情况还是很常见的,而ArrayList不是同步的,所以在不需要同步时使用ArrayList。
比如:添加
在这里插入图片描述
3、散列集hashSet
在java中,散列表用链表数组实现,每个列表被称为桶。要想查找表中对象的位置,就要先计算它的散列码,然后与桶的总数取余,所得到的结果就是保存这个元素的桶的索引。如:一个对象的散列码为76268,有128个桶,那么对象应该保存在108号桶中,如果幸运,这个桶中没有其他元素,那么就将该元素放入桶中。有时候桶被占满了,称为“散列冲突”(hash collision)。这时,需要用新对象与桶中的所有对象进行比较,查看这个对象是否已经存在,如果散列码是合理且随机分布的,桶的数目足够大,需要比较的次数就会很少。

4、树集 treeSet
树集比散列集有所改进,树集是一个有序集合。可以以任何顺序将元素插到集合中,在对集合进行遍历的时候,每个值都将自动地按照排序后的顺序出现。每次将一个元素放入集合中的时候都是放置在正确的位置,因此迭代器总时以排好序的顺序访问每个元素。

5、队列
Queue :继承于Collection
方法:

  • Boolean add(E e) //在有容量限制的队列中添加元素时,如果队列满了,抛出异常IllegalStateException
  • Boolean offer(E e) //队列满了,返回false,在有容量限制的队列中,最好使用offer方法,add方法相对于offer方法而言,有一个专门抛出的异常IllegalStateException,代表容量满了。抛异常处理更加耗时,offer直接返回false的方式更好。
  • E remove() //返回并移除head节点的对象,当queue为空的时候,会抛异常NoSuchElementException
  • E poll() //与remove()相同用法,但是当queue为空的时候返回就是null
  • E element() //返回的是head的对象,当queue为空的时候抛异常NoSuchElementException
  • E peek()//返回的是head的对象,当queue为空的时候返回null

6、优先级队列
优先级的队列可以按照任意的顺序插入,,却总是按照排序的顺序进行检索,就是说,无论合适调用remove方法,总是会获得当前优先级队列中最小的元素。,然而,优先级队列并没有对所有的元素进行排序,如果用迭代的方式处理这些元素,并不需要对它们排序。优先级队列使用了一个优雅且高效的数据结构——堆。堆是一个可以自我调整的二叉树,对树执行add和delete操作,可以让最小的元素移动到根,而不必花费时间对元素进行排序。
使用优先级队列的典型示例就是任务调度。每个任务有一个优先级,任务以随机顺序添加到队列中,每当启动一个新的任务时,都将优先级最高的任务从队列中删除(习惯上将1设为“最高”优先级,所以会将最小的元素删除)。
自我理解:刚开始有点头晕,不过稍微一思考就会明白,删除remove任务的时候就是执行了,利用堆的最小根,每次都删除最小的元素(1),而1就是任务级别最高的,所以没毛病。

7、映射
散列映射(hashMap)和树(TreeMap)映射。散列映射堆键进行散列,树映射用键的整体顺序对元素进行排序,并将其组织成搜索树。
应该选择散列映射还是树映射呢?
与集一样,散列稍微快一点,如果不需要按照排列顺序访问键,就最好选择散列。

散列或比较函数只能作用于键。与键关联的值不能进行散列或者比较。
每当往映射中添加对象时,必须同时提供一个键。要想检索一个对象,必须使用一个键。
如果在映射中没有与给定键对应的信息,get将返回null。
null返回值可能并不方便。又是可以有一个好的默认值,用作为映射中不存在的键。然后使用getOrDefault()方法。

Map<String,Integer> scores=...;
int myscore = scores.get(id,0);//如果输入的id,在scores中并不存在这个键时,返回0

键必须是唯一的,同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值就会取代第一个值。实际上put将返回用这个键参数存储的上一个值。
在这里插入图片描述
枚举所有的键:
在这里插入图片描述
同时查看键和值:
在这里插入图片描述
原来这是访问所有映射条目的最高效的方法,如今,只需要使用forEach方法:
在这里插入图片描述
8、遗留的集合
(1)HashTable类
HashTable类和HashMap类的作用一样,实际上,它们拥有相同的接口。
与Vector类的方法一样,HashTable的方法也是同步的。如果对同步性和遗留代码的兼容性没有任何要求,就应该使用HashMap。
如果需要并发访问,则要使用ConCurrentHashMap。

(2)枚举类Enumeration。两个方法:hasMoreElements和nextElement。这两个方法和Iterator的hasNext()和next()方法很相似。

9、迭代器Iterator:
通过调用next()方法可以访问集合中的元素,但是如果到了集合的末尾,next()方法将会抛出NoSuchElementException异常,所以在使用的时候要结合hasNext()方法使用。
Collection< String> c =….
Iterator it =c.iterator();
while(it.hasNext()){
String str = it.next();

}
类似于for each循环
for(String str:c){
…do something with str
}
foreach可以与任何实现了Iterator接口的对象一起工作。
在使用迭代器删除元素的时候,应该先调用next(),不能直接调用remove()
如果是要删除连续的两个元素:
it.next();
it.remove();
it.next();
it.remove();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值