2016.6.24笔记(3)-集合

来源:互联网 发布:统计局数据采集流程图 编辑:程序博客网 时间:2024/06/06 15:04

换个新的文档吧,这个文档关于struts的配置有问题唉,文档错别字也不少,想想换一个赶紧,趁着这个下载的时间,看一下集合相关的东西

集合/容器

Java集合由CollectionMap两个接口派生而出的:
- Collection代表序列式容器
- Map代表关联式容器.

这里写图片描述

从图片里面可以看到。

Collection

  1. Collection作为List Queue Set等序列式容器的父接口, 提供了一些公共基础方法。collection是最基本的集合接口,一个collection代表一组object。

    1. Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List、set和queue。
  2. 所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。

  3. 如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代器,使用该迭代器即可逐一访问Collection中每一个元素。典型的用法如下:

Iterator it = collection.iterator(); // 获得一个迭代子    while(it.hasNext()) {      Object obj = it.next(); // 得到下一个元素    }

iterator()方法返回一个迭代器Iterator.与其他容器主要用于存储数据不同,Iterator主要用于遍历容器.
Iterator隐藏了各类容器的底层实现细节,向应用程序提供了一个遍历容器的统一接口

方法 释义
1. boolean hasNext()—-Returns true if the iteration has more elements.
2. E next()—-Returns the next element in the iteration.
3. void remove()—-Removes from the underlying collection the last element returned by this iterator (optional operation).

注意: 当遍历Collection时不要使用Collection自带的remove方法删除数据,确实需要删除时,需要使用Iterator提供的remove.
Java 1.5提供foreach循环使得代码更加简洁,但实际foreach迭代容器元素底层也是用的Iterator,这一点可以在调试时看得很清楚.

  public void client() {        System.out.print("before:");        for (Iterator<Integer> iterator = collection.iterator(); iterator.hasNext(); ) {            Integer integer = iterator.next();            System.out.printf(" %d", integer);            if (integer == 0) {                //collection.remove(i);                iterator.remove();            }        }        System.out.printf("%n after:");        for (Integer integer : collection) {            System.out.printf(" %d", integer);        }    }

历史集合类,之所以这样命名是因为从 Java 类库 1.0 发行版就开始沿用至今了。主要差异之一在于所有的操作都和新类不同步.可以往新类中添加同步的实现。

接口 实现 历史集合集 Set HashSet TreeSet List ArrayList Vector LinkedList Stack Map HashSet Hashtable TreeSet Properties

面向接口的编程
Collection collection = new ArrayList();(这样写的好处在于,以后如果要理性不同的集合,可以省略很多麻烦。因为都是用Collection接口里的方法,)

Set

Set接口同样是Collection接口的一个子接口,它表示数学意义上的集合概念。Set中不包含重复的元素,即Set中不存两个这样的元素e1和e2,使得e1.equals(e2)为true。由于Set接口提供的数据结构是数学意义上集合概念的抽象,因此它需要支持对象的添加、删除,而不需提供随机访问。故Set接口与Collection的接口相同,在此对里面的方法不作介绍。

按照定义,Set 接口继承 Collection 接口,而且它不允许集合中存在重复项。所有原始方法都是现成的,没有引入新方法。具体的Set 实现类依赖添加的对象的 equals()方法来检查等同性。

HashSet 类和 TreeSet 类

“集合框架”支持 Set 接口两种普通的实现:HashSet 和TreeSet。
1. 在更多情况下,你会使用 HashSet 存储重复自由的集合,但是呢,Set 接口继承 Collection 接口,而且它不允许集合中存在重复项。
2. 考虑到效率,添加到 HashSet 的对象需要采用恰当分配散列码的方式来实现hashCode() 方法。

虽然大多数系统类覆盖了 Object 中缺省的 hashCode()实现,但创建自己的要添加到 HashSet 的类时,别忘了覆盖 hashCode()。

当要从集合中以有序的方式抽取元素时,TreeSet 实现会有用处。为了能顺利进行,添加到TreeSet 的元素必须是可排序的。 “集合框架”添加对 Comparable 元素的支持,在排序的“可比较的接口”部分中会详细介绍。我们暂且假定一棵树知道如何保持java.lang 包装程序器类元素的有序状态。一般说来,先把元素添加到 HashSet,再把集合转换为 TreeSet 来进行有序遍历会更快。

为优化 HashSet 空间的使用,你可以调优初始容量负载因子
TreeSet 不包含调优选项,因为树总是平衡的,保证了插入、删除、查询的性能为log(n)
HashSet 和 TreeSet 都实现 Cloneable 接口克隆。

Set的使用示例

为演示具体 Set 类的使用,下面的程序创建了一个 HashSet,并往里添加了一组名字,其中有个名字添加了两次。接着,程序把集中名字的列表打印出来,演示了重复的名字没有出现。接着,程序把集作为TreeSet 来处理,并显示有序的列表。

import java.util.*;public class SetExample {  public static void main(String args[]) {    Set set = new HashSet();    set.add("Bernadine");    set.add("Elizabeth");    set.add("Gene");    set.add("Elizabeth");    set.add("Clara");    System.out.println(set);    //将一个hashset集合作为参数传到treeset中,排序。    //符合了上面说的两点,第一就是先把元素添加到 HashSet,再把集合转换为 TreeSet 来进行有序遍历会更快。    //第二呼应了上面对应的collection有两个标准的构造函数,一个无参一个有参。实现了    //有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。这样treeset和传进来的hashset,有相同的元素    Set sortedSet = new TreeSet(set);    System.out.println(sortedSet);  }}

运行程序产生了以下输出。请注意重复的条目只出现了一次,列表的第二次输出已按字母顺序排序。
[Gene, Clara, Bernadine, Elizabeth]
[Bernadine, Clara, Elizabeth, Gene]

List

List 接口继承了 Collection 接口以定义一个允许重复项有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。

查找
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

如果列表本身允许null,可以允许多个null值的存在。
与 set 不同,列表通常允许重复的元素。更正式地说,列表通常允许满足 e1.equals(e2) 的元素对 e1 和 e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素。难免有人希望通过在用户尝试插入重复元素时抛出运行时异常的方法来禁止重复的列表,但我们希望这种用法越少越好。

List 接口在 iterator、add、remove、equals 和 hashCode 方法的协定上加了一些其他约定,超过了 Collection 接口中指定的约定。为方便起见,这里也包括了其他继承方法的声明。

List 接口提供了 4 种对列表元素进行定位(索引)访问方法。列表(像 Java 数组一样)是基于 0 的。注意,这些操作可能在和某些实现(例如 LinkedList 类)的索引值成比例的时间内执行。因此,如果调用方不知道实现,那么在列表元素上迭代通常优于用索引遍历列表

特殊的自己的迭代器,ListIterator,多了两个功能
List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。

List 接口提供了两种搜索指定对象的方法。从性能的观点来看,应该小心使用这些方法。在很多实现中,它们将执行高开销的线性搜索。

List 接口提供了两种在列表的任意位置高效插入和移除多个元素的方法。

注意:尽管列表允许把自身作为元素包含在内,但建议要特别小心:在这样的列表上,equals 和 hashCode 方法不再是定义良好的。

某些列表实现对列表可能包含的元素有限制。例如,某些实现禁止 null 元素,而某些实现则对元素的类型有限制。试图添加不合格的元素会抛出未经检查的异常,通常是 NullPointerException 或 ClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在列表中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。

面向位置的操作包括插入某个元素或 Collection 的功能,还包括获取、除去或更改元素的功能。在 List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。

List 接口不但以位置友好的方式遍历整个列表,还能处理集合的子集:

ListIterator listIterator() ListIterator listIterator(int startIndex) List subList(int fromIndex, int toIndex) 

要点:
**Linked 改快读慢
Array 读快改慢
Hash 两都之间**

Collection是集合接口
|————Set子接口:无序,不允许重复。
|————List子接口:有序,可以有重复元素。

区别:Collections是集合类

Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

Set和List具体子类:
Set
|————HashSet:以哈希表的形式存放元素,插入删除速度很快。

List
|————ArrayList:动态数组
|————LinkedList:链表、队列、堆栈。

Array和java.util.Vector
Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。这是以前老的接口。

Map接口

Map 接口不是 Collection 接口的继承。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。

我们可以把这个接口方法分成三组操作:改变、查询和提供可选视图

改变操作允许从映射中添加和除去键-值对。键和值都可以为 null。但是,不能把Map 作为一个键或值添加给自身。

最后一组方法允许把键或值的组作为集合来处理。

public Set keySet()
public Collection values()
public Set entrySet()
因为映射中键的集合必须是唯一的,用 Set 支持。因为映射中值的集合可能不唯一,用Collection 支持。最后一个方法返回一个实现 Map.Entry 接口的元素 Set

Map.Entry 接口

Map 的 entrySet() 方法返回一个实现Map.Entry 接口的对象集合。集合中每个对象都是底层 Map 中一个特定的键-值对

通过这个集合迭代,可以获得每一条目的键或值并对值进行更改。但是,如果底层 Map 在Map.Entry 接口的 setValue() 方法外部被修改,此条目集就会变得无效,并导致迭代器行为未定义。

HashMap 类和 TreeMap 类

“集合框架”提供两种常规的 Map 实现:HashMap 和TreeMap。和所有的具体实现一样,使用哪种实现取决于你的特定需要。在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果要按顺序遍历键,那么TreeMap 会更好。根据集合大小,先把元素添加到 HashMap,再把这种映射转换成一个用于有序键遍历的 TreeMap 可能更快(这跟hashset一样的)。使用HashMap 要求添加的键类明确定义了 hashCode() 实现。有了TreeMap 实现,添加到映射的元素一定是可排序的。我们将在排序中详细介绍。

为了优化 HashMap 空间的使用,你可以调优初始容量和负载因子。这个TreeMap 没有调优选项,因为该树总处于平衡状态。

HashMap 和 TreeMap 都实现Cloneable 接口。

Hashtable 类和 Properties 类是Map 接口的历史实现。我们将在Dictionary 类、Hashtable 类和 Properties 类中讨论。

映射的使用示例

以下程序演示了具体 Map 类的使用。该程序对自命令行传递的词进行频率计数。HashMap 起初用于数据存储。后来,映射被转换为TreeMap 以显示有序的键列列表。

import java.util.*;

public class MapExample {
public static void main(String args[]) {
Map map = new HashMap();
Integer ONE = new Integer(1);
for (int i=0, n=args.length; i

0 0
原创粉丝点击