Java集合类详解之例子

0、集合结构

Collection

 |—List

  ||—LinkedList

 ||—ArrayList

 ||—Vector

 |└— Stack

 └ Set

Map

 |—Hashtable

 |—HashMap

 └—WeakHashMap


1、Collection接口

  Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些 Collection允许相同的元素而另一些不行。一些能排序而另一些不行。JavaSDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。


 所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后 一个构造函数允许用户复制一个Collection。


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

Iterator it = collection.iterator(); //获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); //得到下一个元素
    }
   由Collection接口派生的两个接口是List和Set。


1.1、List接口

 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和下面要提到的Set不同,List允许有相同的元素。

 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。
 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。


1.1.1、LinkedList类

 LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
 注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。

 一种解决方法是在创建List时构造一个同步的List:
 List list = Collections.synchronizedList(new LinkedList(...));


1.1.2、ArrayList类

 ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
 每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
 和LinkedList一样,ArrayList也是非同步的(unsynchronized)。


1.1.3、Vector类

 Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。


1.1.4、Stack 类

 Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。



1.2、Set接口

 Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
 很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
 请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。


1.3、Map接口

 请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。


1.3.1、Hashtable类

 Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

 Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。


 使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是"one","two","three"

    Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));
 要取出一个数,比如2,用相应的key:
    Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);

 由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方 法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相 同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如 果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希 表的操作。
 如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
 Hashtable是同步的。


1.3.2、HashMap类

 HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。


1.3.3、WeakHashMap类

 WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。


2、总结

 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。


3、同步性

 Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并 不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带 来的不必要的性能开销。

 数据增长从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目 超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最 后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初 始化大小来避免不必要的资源开销。

 使用模式在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用 O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除 元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?

 这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他 的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢 -O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也 会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。
 最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组 (Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。


4、相互区别

4.1、Vector和ArrayList

1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。


2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。


3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。


4,ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!


4.2、arraylist和linkedlist

 1、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
 2、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
 3、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数 据,LinkedList的速度大大优于ArrayList。因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。


4.3、HashMap与TreeMap

 1、HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。HashMap中元素的排列顺序是不固定的)。


 2、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该 使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。

 

 3、在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现,这个TreeMap没有调优选项,因为该树总处于平衡状态。

 结过研究,在原作者的基础上我还发现了一点,二树map一样,但顺序不一样,导致hashCode()不一样。
 同样做测试:
 在hashMap中,同样的值的map,顺序不同,equals时,false;
 而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。


4.4、hashtable与hashmap

 一、历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

 二、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

 三、值:只有HashMap可以让你将空值作为一个表的条目的key或value



5、常用集合例子

集合可理解为一个动态数组。集合类型主要有3种:set(集)、list(列表)、map(映射)。

List 接口:任意存放数据、而且内容可以是重复的

1、ArrayList 类

 同Vector一样是一个基于Array上的链表,但是不同的是ArrayList不是同步的。每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。

实例化: List list = new ArrayList(); 或者 List<String> list = new ArrayList<String>();

例如:

package list_arraylist;

import java.util.*;

/*
 * ArrayList<泛型>
 * 添加数据
 * 获取单个元素
 * 迭代器遍历全部元素
 */
public class AddDom {
	public static void main(String[] args){
		

       List<String> list = new ArrayList<String>();
       list.add("tianjia");
       list.add("manman");
       list.add("buyaoji");
       list.set(2, "改过了");
       
       //获取单个元素
       String li = (String) list.get(2);
       System.out.println(li);
       System.out.println("\n");
       //遍历全部元素
       Iterator<String> iterator = list.iterator();
       while(iterator.hasNext()){
    	   String str = (String) iterator.next();
    	   System.out.println(str);
       }
	}
} 


2、 Vector 类

 基于Array的List,其实就是封装了Array所不具备的一些功能方便我们使用,它不可能走出Array的限制。Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。

实例化: Vector vector = new Vector();

例如:

package list_vector;


import java.util.*;
/*
 * ArrayList会比Vector快,他是非同步的,
 * 如果设计涉及到多线程,还是用Vector比较好一些 
 * 演示Vector的使用。包括Vector的创建、向Vector中添加元素、从Vector中删除元素、 
 * 统计Vector中元素的个数和遍历Vector中的元素。 
*/ 

public class VectorDom {
	public static void main(String [] args){
		
        Vector<String> vector = new Vector<String>(10);
        vector.add("test1");
        vector.add("test2");
        vector.add("test3");
        vector.add("test4");
        vector.add("test5");
        vector.add("test6");
        
        int in = vector.size();
        System.out.println("size:" + in + "\n");       
        vector.remove(3);
        vector.removeElementAt(0);

        Iterator<String> iterator = vector.iterator();
        while(iterator.hasNext()){
        	String string = (String) iterator.next();
        	System.out.println(string);
        }
    }
}


3、LinkedList 类

 不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:

1. 节点本身的数据(data);
2. 下一个节点的信息(nextNode)。所以当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了。这就是LinkedList的优势。

实例化: LinkedList linkedlist = new LinkdList();

例如:

package list_linked;

import java.util.*;

/*
 * LinkedList<String>
 * iterate遍历
 * 添加元素
 * */
public class List_linked {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        LinkedList<String> linked = new LinkedList<String>();
        
        linked.add("linked");
        linked.addFirst("添加到第一个");
        linked.add("艾玛");
        linked.add("li5");
        linked.removeLast();
        linked.remove("艾玛");
        
        Iterator<String> iterator = linked.listIterator();
        while(iterator.hasNext()){
        	String string = (String)iterator.next();
        	System.out.println(string);
        }
	}

}

List总结:

 1、所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。
 2、所有的List中可以有相同的元素。
 3.、所有的List中可以有null元素。

 4.、基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。



2、Set 接口: 不可以加入重复元素、但是可以排序

 HashSet子类:散列存放 HashSet hs = new HashSet();

 TreeSet 子类:有序存放 TreeSet hs = new TreeSet();

例如:

package set_hashset;

import java.util.*;

/*
 * 不可以加入重复元素。
 * 
 * */
public class HashSet_dom {
public static void main(String[] args) {	
		Set<Comparable> hs = new HashSet<Comparable>(6);
		
		hs.add("abc");
		hs.add(new Date());//在HashSet里增加日期对象
		hs.add(new Integer(12));
		
		Iterator<Comparable> it = hs.iterator();
		while(it.hasNext()){ 
			System.out.println(it.next()); 
		} 
	}
}

Set总结:

 1、Set实现的基础是Map(HashMap);

 2、Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象为什么要使用集合类当你事先不知道要存放数据的个数,或者你需要一种比数组下标存取机制更灵活的方法时,你就需要用到集合类。



3、Map 接口:映射与集或列表有明显区别,映射中每个项都是成对的


HashMap 子类

 无序存放,Key不许重复。基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

实例化:Map<String,String> map = new HashMap<String, String>();


Hashtable子类

 无序存放,Key不许重复。

实例化:Map<String,String> map = new Hashtable<String, String>();

例如:

package map;
import java.util.*;

/*
 * Key-Value
 * 成对存在
 * */
public class Map_hashmap {
	public static void main(String[] args) {

	Map<String,String> map = new HashMap<String, String>(); 
		// 添加对象
        map.put("学号:01", "陈游游同学"); 
        map.put("学号:02", "陈君道同学");
        map.put("学号:03", "null");
        
        // 构建Map集合中所有key对象的集合
        Set<String> set = map.keySet(); 
        // 创建迭代器 遍历集合
        Iterator<String> it = set.iterator();                
        while(it.hasNext()){
        	System.out.println(" key:集合中的元素是:" + it.next());
        }
        
        // 构建Map集合中所有value对象的集合
        Collection<String> coll = map.values();  
        it=coll.iterator();        
        while(it.hasNext()){
        	System.out.println(" values:集合中的元素是:" +it.next());
        }
	}

}



4、迭代器的创建和遍历

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

}






0、集合结构

Collection

 |—List

  ||—LinkedList

 ||—ArrayList

 ||—Vector

 |└— Stack

 └ Set

Map

 |—Hashtable

 |—HashMap

 └—WeakHashMap


1、Collection接口

  Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些 Collection允许相同的元素而另一些不行。一些能排序而另一些不行。JavaSDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。


 所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后 一个构造函数允许用户复制一个Collection。


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

Iterator it = collection.iterator(); //获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); //得到下一个元素
    }
   由Collection接口派生的两个接口是List和Set。


1.1、List接口

 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和下面要提到的Set不同,List允许有相同的元素。

 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。
 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。


1.1.1、LinkedList类

 LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
 注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。

 一种解决方法是在创建List时构造一个同步的List:
 List list = Collections.synchronizedList(new LinkedList(...));


1.1.2、ArrayList类

 ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
 每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
 和LinkedList一样,ArrayList也是非同步的(unsynchronized)。


1.1.3、Vector类

 Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。


1.1.4、Stack 类

 Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。



1.2、Set接口

 Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
 很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
 请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。


1.3、Map接口

 请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。


1.3.1、Hashtable类

 Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

 Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。


 使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是"one","two","three"

    Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));
 要取出一个数,比如2,用相应的key:
    Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);

 由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方 法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相 同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如 果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希 表的操作。
 如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
 Hashtable是同步的。


1.3.2、HashMap类

 HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。


1.3.3、WeakHashMap类

 WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。


2、总结

 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。


3、同步性

 Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并 不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带 来的不必要的性能开销。

 数据增长从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目 超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最 后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初 始化大小来避免不必要的资源开销。

 使用模式在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用 O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除 元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?

 这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他 的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢 -O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也 会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。
 最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组 (Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。


4、相互区别

4.1、Vector和ArrayList

1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。


2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。


3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。


4,ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!


4.2、arraylist和linkedlist

 1、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
 2、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
 3、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数 据,LinkedList的速度大大优于ArrayList。因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。


4.3、HashMap与TreeMap

 1、HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。HashMap中元素的排列顺序是不固定的)。


 2、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该 使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。

 

 3、在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现,这个TreeMap没有调优选项,因为该树总处于平衡状态。

 结过研究,在原作者的基础上我还发现了一点,二树map一样,但顺序不一样,导致hashCode()不一样。
 同样做测试:
 在hashMap中,同样的值的map,顺序不同,equals时,false;
 而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。


4.4、hashtable与hashmap

 一、历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

 二、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

 三、值:只有HashMap可以让你将空值作为一个表的条目的key或value

Java之集合(15个demo) 本节主要介绍java的集合,主要包括List、Set和Map,其中List的子类ArrayList和LinkedList,Set的子类HashSet和TreeSet,Map的字类HashMap等,介绍了集合的常用方法,Collections工具类以及Comparable和Comparator排序方法,同时介绍了泛型和集合的嵌套使用等。... 阅读详情

相关推荐

JAVA集合例子

个人资源

Java入门——集合案例

某电影院系统需要在后台存储以下三部电影,然后依次展示。电影名称:电影评分:电影演员:《肖申克的救赎》9.7罗宾斯《霸王别姬》9.6张国荣,张丰毅《阿甘正传》9.3汤姆.汉斯克//无参构造器//有参构造器//设置getter/setter方法//1.定义电影类//2.创建三个电影对象Movie m1 = new Movie("《肖申克的救赎》" , 9.7 , "罗宾斯");

weixin_61275790的博客 1119

JAVA-集合例子

java集合的经典例子,倾心奉献,代码都是我自己写的,希望对你们有帮助

java 字典_菜鸟程序员都能听得懂得Java集合介绍,快来收藏

一、集合是什么 ?1. 集合知识概念前面我们学习过了,Java中的基本类型,任何单一的数据都可以用基本类型来表达,这些单一的基本类型被统一的组合或者管理起来的就是集合,或者叫容器也可以。举例:我们用数据来表示一个学校的存在。首先我们先来分析一波,学校的组成。学校的组成 = 班级的集合班级 = 学生的集合前面我们说了,单一的数据类型都可以用基本类型来表示。那么我们用 String 类型来表示学生的名...

weixin_39553423的博客 441

基于结构的虚拟筛选模型 gnina 从源码编译

所需要的软件安装包: 安装 CUDA 装的时候看着点,第二个要你装驱动的选择,回答N,不装。 sudo sh cuda_10.0.130_410.48_linux.run sudo vim ~/.bashrc 在 ~/.bashrc 文件最后加上 export PATH=/usr/bin:/usr/local/cuda-10.0/bin${PATH} export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:${LD_LIBRARY_PATH} source ~

周迪新的博客 3190

Hypermesh2021实战:塑料圆盘结构化网格划分全流程(附避坑指南)

本文详细介绍了使用Hypermesh2021进行塑料圆盘结构化网格划分的全流程操作,包括几何预处理、网格生成策略及质量验证。特别针对工程实践中常见的12个典型问题提供解决方案,帮助用户提升CAE仿真分析的精度和效率。

weixin_29294597的博客 320

java集合举例_Java集合

集合与数组存储数据概述:集合、数组都是对多个数据进行内存存储操作的结构,简称Java容器。数组存储的特点:一旦初始化以后,其长度就确定了。数组一旦定义好,元素类型也就确定了,我们也就只能操作指定类型的数据了。比如:String[] arr;int[] arr1;Object[] arr2;数组存储的弊端:一旦初始化以后,其长度就不可修改。数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常...

weixin_39929918的博客 456

pyinstaller+scrapy打包出现错误:OSError: could not get source code

错误如下: Traceback (most recent call last): File "scrapy\utils\defer.py", line 55, in mustbe_deferred File "scrapy\core\spidermw.py", line 60, in process_spider_input File "scrapy\core\scraper.py", line 152, in call_spider File "scrapy\utils\misc.py

kin的博客 1760

java集合示例_java常用集合示例

/*一些常用的集合类的方法的用法演示。JAVA容器的两种基本类型:区别在于每个位置保存的元素个数Collection:一组独立的元素通常都 要服从某种规则。List按对象进入的顺序保存对象,不做排序和编辑;而set则是不能有重复的元素,即每个对象只接受一次,并有自己的内部的排序算法。Map:一组成对的“键值对”对象,get()时一般返回Entry -->是一种专门针对Hash容器的数据类型,...

weixin_36225384的博客 506

OpenCV函数用法之calibrateCamera

参考链接:opencv中标定函数calibrateCamera_ychl87的专栏-优快云博客 世界坐标系的三维点投影到成像坐标系中的二维点的投影公式如下: 其中(X,Y,Z)为世界坐标系中的三维点; (u,v)为成像面坐标系中的二维点; A为相机的内参数矩阵:(cx,cy)为主光轴点,一般为图像的中心;fx和fy为焦距; [R|t]为相机的外参数矩阵:R为旋转矩阵,t为位移矩阵; 上述公式的简单推理过程如下 考虑到镜头畸变 其中,k1,k2,k3,k4,k5和k6为径向畸变,p1和.

tiger&sheep的博客 3万+

Oracle 19c RAC安装踩坑实录:OpenSSH 8.x版本与OUI的“兼容性战争”及一劳永逸的解决思路

本文深入解析Oracle 19c RAC在Linux8环境中部署时遇到的OpenSSH 8.x版本兼容性问题,特别是[INS-06006]错误的根源与解决方案。从协议层分析冲突本质,提供SCP包装器技术、官方补丁应用指南及现代化部署体系构建三种解决方案,帮助企业高效完成RAC安装并规避类似问题。

weixin_42648844的博客 459

java常用集合类详解(有例子,集合类糊涂的来看!)

Collections Framework 集合框架是一个统一的架构,用来表示和操作集合. 集合框架主要是由接口,抽象类和实现类构成. 接口:蓝色;实现类:红色 Collection |_____Set(HashSet) |         |_____SortedSet(TreeSet) |_____List(LinkedList,ArrayList) Collection:集合

想作会飞的鱼的博客 658

SPICE模型入门到精通

文章目录前言一、SPICE是什么?二、1. 前言 由于笔者的毕业设计与功率半导体器件建模相关,需要用到SPICE软件来建模,在这记录一下从零开始的SPICE学习历程~ 一、SPICE是什么? 电子产品的设计一般先从功能框图开始,然后细化到原理图,还要经过很调试验证过程,最终才能完成。调试和验证的过程复杂而繁琐,在设计集成电路时更是如此,在制造之前急需验证集成电路的功能。 根据电路理论,人们可以建立起节点方程和回路方程,通过解这些方程组成的方程组就可以得到结果,也就是说可以通过计算来获得电路的工作情况。但

qq_42031914的博客 7万+

java集合类详解_java常用集合类详解(有例子,集合类糊涂的来看!) .

Framework集合框架是一个统一的架构,用来表示和操作集合.集合框架主要是由接口,抽象类和实现类构成.接口:蓝色;实现类:红色Collection|_____Set(HashSet)| |_____SortedSet(TreeSet)|_____List(LinkedList,ArrayList)Collection:集合层次中的根接口,JDK没有提供这个接口的实现类。Set:...

weixin_42232139的博客 223

Arduino与Proteus仿真实例-LCD2004-I2C(PCF8574)驱动仿真

LCD2004-I2C(PCF8574)驱动仿真 PCF8574/74A 通过两线双向 I2C 总线(串行时钟 (SCL)、串行数据 (SDA))提供通用远程 I/O 扩展。 LCD2004,即2004字符型液晶显示器,是一种点阵模块,用于显示字母、数字、字符等。 它由 5x8 个点阵位置组成; 每个位置可以显示一个字符。 两个字符之间有一个点间距,行之间有一个空格,从而将字符和行分开。 模型 2004 表示它显示 4 行,每行 20 个字符。 在前面的实例中对PCF8574和LCD2004的已经做了详细介

视觉与物联智能 1165

GEO的工作原理,以及GEO会催生出更多的爬虫岗位吗?

摘要: GEO(生成式引擎优化)是提升内容在AI搜索(如ChatGPT、Perplexity等)中引用率的新策略,核心在于优化内容的可抓取性、语义清晰度、权威性。与传统SEO不同,GEO聚焦AI的引用逻辑,需通过爬虫监控AI回答、逆向分析引用源特征(如结构化数据、权威背书),并构建自动化工具优化内容。爬虫工程师需转型为“AI可见性基础设施构建者”,重点关注高权威站点、知识库及官方信息源,同时确保技术可抓取性(如放行AI爬虫UA)。GEO的核心是从“排名”转向“被AI引用”,强调实体识别与动态对话适配。

数据知道的博客 4642

java语言中 常用的集合类有_java常用集合类详解(有例子,集合类糊涂的来看!)...

Collections Framework集合框架是一个统一的架构,用来表示和操作集合.集合框架主要是由接口,抽象类和实现类构成.接口:蓝色;实现类:红色Collection|_____Set(HashSet)| |_____SortedSet(TreeSet)|_____List(LinkedList,ArrayList)Collection:集合层次中的根接口,JDK没有提供这...

weixin_39536427的博客 108

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java常用集合类详解

什么是集合类 简单来讲:集合就是一个放数据的容器,准确的说是放数据对象引用的容器 集合类存放于java.util包中。 集合类型主要有3种:set(集)、list(列表)和map(映射)。 集合存放的都是对象的引用,而非对象本身。所以我们称集合中的对象就是集合中对象的引用。 集合类有哪些 Set List和Set都是集合,一般来说:如果我们需要保证集合的元素是唯一的,就应该想到用Set集合,比如说:现在要发送一批消息给用户,我们为了减少「一次发送重复的内...

Wangxichuan_Jack的博客 588

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java集合类详解

Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口   Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Element

毛凡的博客 17万+

Java 集合类详解

通过本篇技术博客的介绍,我们了解了 Java 语言中常用的集合类的概念、分类、使用方法和最佳实践。在实际开发中,集合类是非常重要的数据结构,熟练掌握集合类的使用方法和最佳实践能够提高程序的性能和可读性,推荐大家多加练习和实践。

hj1993的博客 1842
上一篇: java—网络通信socket的例子
下一篇: Java集合类详解之例子
AndyChen9988
博客等级 码龄11年 276粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值