[转]Java之Collection/Map

转自:

http://www.cnblogs.com/mingcn/archive/2010/10/22/JavaContainer.html

Java复习笔记——容器知识点总结

Java中容器分两类,一种是单值的Collection,一种是储存键-值对的Map

Collection

又分两种,Set和List,区别在于Set是不可重复的,而List是可重复的

Set

常用有两种:HashSet和TreeSet,其内部实现是一个Map,它的元素就相当于Map中的Key,而Value是一个Object常量


1

2

3

4

5

6

7

private transient HashMap<E,Object> map;

private static final Object PRESENT = new Object();

public HashSet() {

    map = new HashMap<E,Object>();

}


1

2

3

4

5

6

7

private transient NavigableMap<E,Object> m;

private static final Object PRESENT = new Object();

public TreeSet() {

    this(new TreeMap<E,Object>());

}

所有对Set的操作都被最终转嫁为对Map的操作,具体细节在下面Map中讲述

List

对Collection接口进行了简单的扩充,你可以将任何对象放到放到一个List容器中,并在需要时从中取出。

常用的有ArrayList和LinkedList,都是有顺序,可重复的集合类型

ArrayList:顾名思义,数据列表,其实就是封装了一个数组,因此它的访问速度极快


1

2

3

private transient Object[] elementData;

private int size;

然后封装了一些对数组的常用操作如插入、删除等。

说到ArrayList不得不提下Arrays类和数组[]

ArrayList可以储存不同类型的对象(虽然一般不推荐这样做),而数组只能是同一类型

ArrayList可以动态增加长度,但效率不高,而数组只能是固定长度,却十分高效。每当执行add/insert等添加元素的方法,都会先检查数组长度是否足够,如果是,它就会以当前容量的3/2倍+1来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。

ArrayList提供常用方法,add/get/indexOf/remove等,而相应的Arrays没有提供add和remove方法,查询元素索引要先sort再binarySearch

ArrayList排序需外部方法Collections.sort(..),数组排序则使用Arrays.sort(..),二者都可以使用自然顺序(实现Comparable)或用Comparator指定

LinkedList:很显然的是链表,内部实现是带头结点的双向链表,适合于在链表中间需要频繁进行插入和删除操作


1

2

3

4

5

6

7

8

9

10

11

12

private transient Entry<E> header = new Entry<E>(null, null, null);

private transient int size = 0;

private static class Entry<E> {

    E element;

    Entry<E> next;

    Entry<E> previous;

//..

}

Map

是一种把键和值对象进行关联的容器,类比Collection,可以这样说:Collection对象中某个值的ID是它在容器中的索引值,而在Map中,某个值的ID是它对应的键。这样我们使用Map时就不用局限于int型的索引值,可以用任何类型的对象作索引。正是由于Key的索引特性,Map中不允许有同值的Key存在(前文讲到Set内部实现是Map中的Key的集合,所以Set的元素不能重复)。当然,Value是可以重复的,甚至可以是同一个Reference。Map在处理相同的Key时,将新值存入,旧值被替换并返回

HashMap采用Hash算法,以便快速查找某个元素。

将键的哈希值作为内存索引依据,内部实现是一个适当长度的链式数组,由Key的Hash值对应数组下标,再间接对应内存,是一种比较高效的存取方式。Key的hashCode()相同的情况下,放在同一个单项链表结构中。

一个HashMap中Key的类型应该重写hashCode()方法,保证在两个对象equals为true时返回相同的值,否则在重复性检查时会直接被当做不同的键,造成不可预期的后果。

Hash容器中判断重复的方式:

先比较hash(key.hashCode())是否相同,hash(int)是一个内部算法,具体细节不作讨论

  不同,则不重复

  相同,则

    比较两个Key是否是同一引用

      是,则重复

      不是,再调用equals方法

        返回true则重复

        返回false则不重复

TreeMap:采用树型储存结构按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。

内部实现是一颗二叉排序树,其中序遍历结果为递增序列。所以要求他的Key必须是Comparable或者创建TreeMap的时候指定Comparator。

当Key实现Comparable<E>接口时,必须实现comparaTo(E e)方法,当使用外部比较器(Comparator<T>)时,需实现Comparator<T>的compare(T t1, T t2)方法

相关知识

泛型(Generic)

泛型允许Coding的时候可以定义一些可变的类型,但必须在使用前进行声明具体是哪种类型


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class testGeneric<T> {

    T t;

    testGeneric(T t) {

        this.t = t;

    }

}

class test {

    testGeneric<String> tgs = new testGeneric("Hi,Gineric!");

    testGeneric<Integer> tgi = new testGeneric(100);//AutoBoxing

    {

        System.out.println(tgs.t);//Output:Hi,Gineric!

        System.out.println(tgi.t);//AutoUnBoxing&Output:100

    }

}

需要注意Java 泛型的类型参数之实际类型在编译时会被消除(upcast to Object),所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

迭代器(Iterator)

提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

对于遍历一个容器中所有的元素,Iterator模式是首选的方式

Collection定义了Iterator<E> iterator()方法,子类都各自实现了该方法,我们直接调用即可

Map中虽没有定义,我们可以利用map.entrySet()的iterator()方法


1

2

3

4

5

6

7

Iterator i = someMap.entrySet().iterator();

while(i.hasNext()) {

    Map.Entry entry = (Map.Entry) i.next();

    Object key = i.getKey();

    Object value = i.getValue();

    //something TODO

}

或者转换为Collection(Set)用增强For循环


1

2

3

4

5

6

Set<Map.Entry> entrySet = someMap.entrySet();

for(Map.Entry entry : entrySet){

    Object key = entry.getKey();

    Object value = entry.getValue();

    //something TODO

}

ListIterator继承了Iterator,提供了对List的双向遍历的方法。

需要注意的是,调用Iterator的remove方法,删除的是最后一次调用next()(or previous(),if possible)所返回的元素

如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。

也就是说,调用Iterator时,最好不要调用Collection的add/remove等方法

另:容器类的toString()方法也是通过调用iterator()方法来实现遍历

  对集合使用增强的for循环也是隐式地调用iterator()方法

还有Stack、Queue等结构,操作简单,不作赘述

时间: 2024-08-06 16:02:53

[转]Java之Collection/Map的相关文章

java集合 Collection,Map

大致分为Set,List,Queue,Map四种体系 Set代表无序不可重复的集合,通过元素本身访问 List代表有序可重复的集合,通过元素索引访问 Map代表有映射关系的集合,通过key访问 Queue代表一种队列集合的实现 Collection接口是List,Set,Queue的父接口,定义了如下操作集合方法:add,addAll,clear,contains,containsAll,isEmpty,iterator,remove,removeAll,retainAll,insize,toA

java集合 - Collection - List - Set - Map - Iterator 学习笔记

1.Collection接口 集合可以理解为一个动态的对象数组,两层含义: 1).动态:集合中的对象可以任意扩充和删减: 2).集合中可以存放任意对象. 集合的性能比数组高,而且更容易进行数据的扩展和修改. Collection的常用子接口:List.Set.Queue. 2.List接口 List集合可以存放任意对象,而且集合中对象可以重复. List的常用实现类:ArrayList.Vector. ArrayList与Vector的比较: 性能方面:ArrayList采用异步处理方式,性能高

java 容器Collection List Set Map概述

对JAVA的集合的理解是想对于数组 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型) JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用类型的的数据,不能存放基本数据类型. JAVA集合主要分为三种类型: Set(集) List(列表) Map(映射) Collection 接口 Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法. Set 和

Collection Map Java数据结构

Collection Map 框架图 Collection          接口的接口   对象的集合 ├ List                   子接口      按进入先后有序保存   可重复 │├ LinkedList                接口实现类   链表   插入删除   没有同步   线程不安全 │├ ArrayList                  接口实现类   数组   随机访问   没有同步   线程不安全 │└ Vector             

JavaSE:集合总结(Collection,Map)

今天来总结JavaSE部分的集合.首先来从整体来看: 我们主要要学习的内容: Collection: Collection(接口): java.util.Collection |-- List(子接口) : |--ArrayList |--LinkedList |--Vector |-- Set(子接口) : |--AbstracSet(子接口) |--HashSet |--LinkedHashSet |--SortedSet(子接口) |--TreeSet |-- Queue(子接口) : M

Java中的Map List Set等集合类

Map List Set等集合类: 一.概述 在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系: +Collection 这个接口extends自 --java.lang.Iterable接口 ├+List(接口 代表有序,可重复的集合.列表) │├ ArreyList     (Class 数组,随机访问,没有同步,线程不安全) │├ Vector        (Class  数组                   同步        线程全) │

java集合框架--Map集合

1.Map集合的概述 Map集合是将键映射到值的对象.一个映射不能包含重复的键.每个键最多只能映射到一个值. 2.Map接口和Collection接口的不同? Map集合存储元素是成对出现的,Collection集合存储元素是单独出现的. Map集合的键是唯一的,值是可重复的. Collection集合的子接口Set是唯一的,List是可重复的. Map集合的数据结构值针对键有效,和值无关,而Collection接口的数据结构是针对元素有效. 3.Map集合示例及功能 package cn; i

java并发容器(Map、List、BlockingQueue)

转发: 大海巨浪 Java库本身就有多种线程安全的容器和同步工具,其中同步容器包括两部分:一个是Vector和Hashtable.另外还有JDK1.2中加入的同步包装类,这些类都是由Collections.synchronizedXXX工厂方法.同步容器都是线程安全的,但是对于复合操作,缺有些缺点: ① 迭代:在查觉到容器在迭代开始以后被修改,会抛出一个未检查异常ConcurrentModificationException,为了避免这个异常,需要在迭代期间,持有一个容器锁.但是锁的缺点也很明显

java中一个Map要找到值Value最小的那个元素的方法

import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MinMapDemo {     public static void main(String[] args) {         Map<Integer, Integer> map = new HashMap<Int