现在的位置: 首页 > 综合 > 正文

JAVA 中的 List,Set,Map

2014年09月05日 ⁄ 综合 ⁄ 共 4070字 ⁄ 字号 评论关闭

JAVA 中的 List,Set,Map


List,Set,Map 之间的类关系如下:

Collection   
├List  
│├LinkedList  
│├ArrayList  
│└Vector  
│ └Stack  
└Set  
Map  
├Hashtable  
├HashMap  
└WeakHashMap  

Collection 是最基本的集合接口,代表了一组 Object 的集合。其中的元素根据实例化的子类有不同的规则,有的集合元素可以重复存在,而有些集合元素则是唯一的;有的集合可以排序,有的不能。

只要是 Collection 对象,都可以用同一个方法遍历所有元素 :

Iterator iterator = list.iterator();
while(iterator.hasNext()) {
    System.out.println(iterator.next());
}

Collection 接口派生的两个接口为 List,Set

List

List 接口为一个有序的 Collection ,能够精确的控制每个插入元素的位置,并能够使用类似数组下标的索引来访问元素。

与 Set 不同,List 允许有相同元素。

List 还提供了一个 listIterator() 方法,返回一个 ListIterator 接口,相比于 Iterator, ListIterator 增加了向前遍历、向后遍历 List 、添加元素、set 元素、删除元素等操作:

        LinkedList<String> list = new LinkedList<String>();
        list.add("sdsd");
        list.add("sdsd1");
        list.add("sdsd2");
        list.add("sdsd3");
//        Iterator iterator = list.iterator();
//        while(iterator.hasNext()) {
//            System.out.println(iterator.next());
//        }
        ListIterator<String> iterator = list.listIterator();
        System.out.println("next:" + iterator.next());//next返回下一个值,游标前进
        iterator.add("sdsd9");//add插入在next返回值之前,previous返回值之后,且之后游标会前进
        System.out.println("next2:" + iterator.next());
        iterator.add("sdsd8");
        System.out.println("previous2:" + iterator.previous());//previous返回前一个值,游标后退
        iterator.set("sdsd88");//用指定的值替换next或previous最后一次返回的元素的值
        iterator.add("22");
        iterator.add("11");
        for(int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

实现 List 接口的类常用的有 ArrayList,LinkedList,Vector,Stack

ArrayList

  • 可变大小的数组
  • 允许所有元素,包括 null
  • 非同步 (unsynchronized)
  • ArrayList 实例都有一个容量 (Capacity),即用于存储元素的数组大小。会随着添加新元素而增加大小。当需要插入大量元素时,可以调用 ensureCapacity() 来增加容量以提高效率

LinkedList

  • 允许元素为 null
  • 额外提供了对首元素和尾元素的 get,remove,insert, 所以 LinkedList 可用于堆栈(stack)、队列(queue)、双向队列(deque)
  • 非同步,多线程同时访问该 List 时实现同步的一个方法是:
List syncList = Collections.synchronizedList(new LinkedList<Object>());

Vector

  • 与 ArrayList 类似,都是实现了一个可增长的数组
  • 同步的,由于 Vector 是同步的,由 Vector 所创建的 Iterator, 虽然与 ArrayList 创建的 Iterator 为同一接口, 但是,当一个 Iterator 被创建并使用,另一个线程改变了 Vector 的状态(例如,添加或删除了一些元素),这时调用 Iterator 的方法会抛出 ConcurrentModificationException,因此必须捕获该异常。

Stack

  • Stack 继承自 Vector
  • 实现了一个后进先出的堆栈。
  • 作为堆栈提供了5个额外的方法:
    • push: 添加一个元素到 Stack 顶部
    • pop: 移除 Stack 元素,并将该移除元素作为函数的返回值返回
    • peek: 获取 Stack 顶部元素,并不移除它
    • search: 检测一个元素在 Stack 中的位置
    • empty: 检测 Stack 是否为空

Set

Set 是一种不包含重复元素的 Collection ,通过对象的 equals 方法来对比。最多有一个 null 元素

注意:小心操作可变对象(Mutable Object)。如果 Set 中的元素改变导致 e1.equals(e2) = true 将导致一些问题。

HashSet

  • 由 HashMap 作为内部数据支持,存取速度比较快
  • 存储顺序与添加元素顺序无任何关联

LinkedHashSet

  • 存储顺序为添加元素顺序

TreeSet

  • 对 Set 中的元素进行排序存放

Map


Map没有继承 Collection 接口

Map 提供 Key 到 Value 的映射。一个 Map中不能包含相同的 Key,每个 Key 只能映射一个 Value。 Map 接口提供3种集合的视图,Map 的内容可以被当作一组 key 集合,或一组 Value 的集合,或一组 Key-Value 的集合。

为了更好的遍历 Map ,可以使用 Map.Entry ,其中 K,V 代表了 Map 的键与值。

调用 Map 的 entrySet 会返回一个 Set<map.entry> 。

遍历 Map 的例子如下:

Map<String, String> map = new HashMap<String, String>();
map.put("test1", "1");
map.put("test1", "2");
map.put("test2", "3");
map.put("test3", "4");
map.put("test4", "5");
map.put("test5", "5");
map.put("test1", "5");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for(Map.Entry<String, String> entry : entrySet) {
    System.out.println(entry.getKey() + "," + entry.getValue());
}

Hashtable

  • 实现一个 Key-Value 映射的哈希表。
  • 任何非空对象都可作为 Key 或 Value
  • 由于作为 Key 的对象将通过计算其散列函数来确定与之对应的 Value 的位置,因此作为 Key 的对象都必须实现 hashCode 和 equals 方法。如果是自定义的对象作为
    Key ,必须要重写 hashCode 和 equals
  • 同步的

HashMap

  • 与 Hashtable 类似
  • 非同步
  • 允许 null 作为 Key 或 Value

WeakHashMap

  • 以弱键实现的基于哈希表的 Map
  • 在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。
  • 其实就是除了本map引用以外, 没有其他对象引用该key对象, 则WeakHashMap会自动移除这个key以及对应的值.

IdentityHashMap

  • 此类利用哈希表实现 Map 接口
  • 比较键(和值)时使用引用相等性代替对象相等性。换句话说,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等(在正常 Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : k1.equals(k2)))。
  • 根据此特性可以实现重复Key
  • 也就是说, 如果Key是同一个对象才算是键相等, 如果只是值相等, 那么不算相等.例如:

      Map<Pet, String> map = new IdentityHashMap<Pet, String>();
      Pet p = new Pet("eric");
      map.put(new Pet("eric"), "eric");
      map.put(new Pet("eric"), "hello");
      System.out.println("size = " + map.size());
    
      Map<Pet, String> hashMap = new HashMap<Pet, String>();
      hashMap.put(new Pet("eric"), "eric");
      hashMap.put(new Pet("eric"), "hello");
      System.out.println("hashMap size = " + hashMap.size());
      //Pet中的equals中只要name相等, 就算这两个pet对象相等. 
      //执行结果为: size = 2 ;hashMap size = 1

总结

  • 涉及到堆栈,队列等操作,应该考虑用 List
  • 需要快速插入,删除,使用 LinkedList
  • 需要快速随机访问元素,使用 ArrayList
  • 单线程环境考虑非同步类,多线程考虑同步类



转自:
http://blog.csdn.net/abbuggy/article/details/7720666
http://www.blogjava.net/rain1102/archive/2009/05/15/270890.html
【上篇】
【下篇】

抱歉!评论已关闭.