Java中的集合类

Java中的集合类

(Collection framework)我们在前面学习过java数组,java数组的程度是固定的,在同一个数组中只能存放相同的类型数据。数组可以存放基本类型的数据,也可以存入对象引用的数据。

在创建数组时,必须明确指定数组的长度,数组一旦创建,其长度就不能改变,在许多应用的场合,一组数据的数目不是固定的,比如一个单位的员工数目是变化的,有老的员工跳槽,也有新的员工进来。

为了使程序方便地存储和操纵数目不固定的一组数据,JDK中提供了 java集合类,所有java集合类都位于java.util包中,与java数组不同,java集合类不能存放基本数据类型数据,而只能存放对象的引用。

Java集合类分为三种

Set(集合)集合中对象不按特定的方式排序。并且没有重复对象,但它有些实现类中的对象按特定方式排序。--无序,不能重复

List(列表):集合中的对象按照检索位置排序,可以有重复对象,允许按照对象在集中的索引位置检索对象,List和数组有些相似。--有序,可以重复

Map(映射):集合中的每一个元素包含一对键对象和值对象,集合中没有重复的键对象,值对象可以重复,它的有些实现类能对集合中的键对象进行排序。

 

Java的主要集合类的框架图

CollectionIterator接口

Collection接口中声明了适用于java集合(只包括SetList)通用方法。

Collection接口的方法

方法

描述

boolean add(Object o)

向集合中加入一个对象的引用

void  clear( )

删除集合中所有对象,即不再对持有对象的引用

boolean contains(Object o)

判断在集合中是否含有特定对象的引用

boolean isEmpty()

判断集合是否为空

Iterator iterator( )

返回一个Iterator对象,可用它来遍历集合中的元素

boolean remove(Object o)

从集合中删除一个对象的引用

int size( )

返回集合中元素的数目

Object [ ] toArray()

返回一个数组,该数组包含集合中的所有元素

Set接口和List即可都继承了Collection接口,而Map接口没有继承Collection接口,因此可以对Set对象和List对象调用以上方法,但是不能对Map对象调用以上方法。

Collection接口的iterator()toArray()方法多用于获得集合中的所有元素,前者返回一个Iterator对象,后者返回一个包含集合中所有元素的数组。

Iterator隐藏底层集合的数据结构,向客户程序提供了遍历各种类型的集合的统一接口。

Iterator接口中声明了如下方法:

l  hasNext():判断集合中的元素是否遍历完毕,如果没有,就返回true

l  next():返回下一个元素

l  remove():从集合中删除上一个由next()方法返回的元素。

 

注意:如果集合中的元素没有排序,Iterator遍历集合中元素的顺序是任意的,并不一定与像集合中加入的元素的顺序一致。

 

Set(集)

  Set是最简单的一种集合,集合中的对象不按特定方式排序,并没有重复对象。Set接口主要有两个实现类:HashSet类还有一个子类LinkedHashSet类,它不仅实现了哈希算法,而且实现了链表数据结构,链表数据结构能提高插入核算出元素的性能。TreeSet类实现了SortedSet接口中,具有排序功能。

List(列表)

List的主要特征使其元素已先行方式存储,集合中允许存放重复对象。List接口主要的实现类包括:

l  ArrayList—ArrayList代表长度可变的数组。允许对元素进行快速的随机访问,但是向ArrayList中插入与删除元素的速度较慢。

l  LinkedList—在实现中采用链表数据结构。对顺序访问进行了优化,向List中插入和删除元素的速度较快,随机访问速度则相对较慢,随机访问是指检索位于特定索引位置元素。

Map(映射)

Map(映射)是一种吧键对和值对象进行映射的集合。它的每一个元素都包含一对键对象和值对象,而之对象仍可以是Map类型。以此类推,这样就形成了多级映射。向Map集合中加入元素时,必须提供一对键对象和值对象,从Map集合上检索元素只要给出键对象,就会返回值对象。

实例1

CollectionAll.java

package collection;

import java.util.ArrayList;

import java.util.Collection;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Iterator;

import java.util.LinkedHashMap;

import java.util.LinkedHashSet;

import java.util.LinkedList;

import java.util.List;

import java.util.Hashtable;

import java.util.Map;

import java.util.Set;

import java.util.SortedMap;

import java.util.SortedSet;

import java.util.TreeMap;

import java.util.TreeSet;

 

public class CollectionAll {

       public static void main(String args[]){

              List list1=new LinkedList();

             

              list1.add("");

              list1.add("");

              list1.add("");

              list1.add("");

              traverse(list1);

             

              List list2=new ArrayList();

              list2.add("");

              list2.add("");

              list2.add("");

              list2.add("");

              traverse(list2);

      

              Set set1=new HashSet();

              set1.add("");

              set1.add("");

              set1.add("");

              set1.add("");

              traverse(set1);

             

              SortedSet set2=new TreeSet();

              set2.add("");

              set2.add("");

              set2.add("");

              set2.add("");

              System.out.println(set2.size());

              traverse(set2);

             

              LinkedHashSet set3=new LinkedHashSet();

              set3.add("");

              set3.add("");

              set3.add("");

              set3.add("");

              traverse(set3);

             

              Map m1=new HashMap();

              m1.put("name05","");

              m1.put("name06","");

              m1.put("name08","");

              m1.put("name09","");

              traverse(m1.keySet());

              traverse(m1.values());

             

              SortedMap m2=new TreeMap();

              m2.put("name01","");

              m2.put("name02","");

              m2.put("name03","");

              m2.put("name04","");

              traverse(m2.keySet());

              traverse(m2.values());

      

           LinkedHashMap m3=new LinkedHashMap();

              m3.put("name01","");

              m3.put("name02","");

              m3.put("name03","");

              m3.put("name04","");

              traverse(m3.keySet());

              traverse(m3.values());

             

          Hashtable numbers=new Hashtable();

              numbers.put("name01","");

              numbers.put("name02","");

              numbers.put("name03","");

              numbers.put("name04","");

              traverse(numbers.keySet());

              traverse(numbers.values());

       }

              static void traverse(Collection coll) {

                     Iterator iter=coll.iterator();

                     while(iter.hasNext()){

                            String elem=(String)iter.next();

                            System.out.print(elem+" ");

                     }

                     System.out.println();

              }

       }

一.  集合框架中的各种实现类

HashSet

HashSet类按照哈希算法---存取集合中的对象,具有很好的存取和查找功能。当向集合中加入一个对象时,HashSet对调用对象的hashCode()方法来多的哈希码,然后根据这个哈希码进一步计算出对象在集合中的存放位置。

 

实例2  MyHashSet.java

package collection;

import java.util.*;

public class MyHashSet{

       public static void main(String args[]){

              HashSet set=new HashSet(6);

              Object[] values={"Tom","Mike","Mary","Linda","Jone","Jack"};

              for(int i=0;i<values.length;i++){

                     values[i].hashCode();

                     set.add(values[i]);

                     System.out.println(set.hashCode());

              }

              set.remove("Mike");

              System.out.println("size="+set.size());

              Iterator iter=set.iterator();

              while(iter.hasNext()){

                            String elem=(String)iter.next();

                            System.out.println(elem+" ");

              }

              System.out.println(set.contains("Jack"));

              System.out.println(set.contains("Linda"));

              System.out.println(set.contains("Mike"));

       }

}

 

TreeSet

 TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序,一下程序创建了一个TreeSet对象,然后向集合中加入了4Integer对象

 

实例3

TreeSetTest.java

package collection;

import java.util.*;

public class TreeSetText{

       public static void main(String args[])   {

              Set set=new TreeSet();

              set.add(new Integer(8));

              set.add(new Integer(7));

              set.add(new Integer(6));

              set.add(new Integer(9));

              Iterator it=set.iterator();

              while(it.hasNext())

              System.out.println(it.next()+"");

       }

}

由此我们知道当TreeSet集合中加入一个对象时,会把它插入到有序的对象序列中。

 

ArrayList

ArrayList—ArrayList代表长度可变的数组。允许对元素进行快速的随机访问,它允许所有元素,有包括nullArrayList是线程不同步的,向ArrayList中插入与删除元素的速度较慢

LinkedList

LinkedList—实现了List接口,允许null元素,在实现中采用链表数据结构。对顺序访问进行了优化,向List中插入和删除元素的速度较快,随机访问速度则相对较慢,随机访问是指检索位于特定索引位置元素。

注意:LinkedList没有同步方法。如果多个线程同时访问一个List,则必须实现访问同步。

一种解决方法是在创建List时构造一个同步的List

List list=Collection.synchronizedList(new List(…));

实例4

StackL.java

package collection;

import java.util.LinkedList;

public class StackL{

       private LinkedList list=new LinkedList();

       public void push(Object v){

              list.addFirst(v);

       }

       public Object top() {

              return list.getFirst();

       }

       public Object pop()       {

              return list.removeFirst();

       }

       public static void main(String args[])   {

              StackL stack=new StackL();

              for(int i=0;i<10;i++)

              stack.push(new Integer(i));

              System.out.println(stack.top());

              System.out.println(stack.top());

              System.out.println(stack.pop());

              System.out.println(stack.pop());

              System.out.println(stack.pop());

       }

}

 

ListIterator接口

ListlistIterator()方法返回一个ListIterator对象,ListIterator接口继承了Iterator接口,此外还提供了专门操控列表的方法。

l  add():向列表插入一个元素

l  hasNext():判断列表中是否还有下一个元素

l  hasPrevious():判断列表中是否还有上一个元素

l  next():返回列表中的下一个元素

l  previous():返回列表中的上一个元素

  实例5

ListIterator.java

import java.util.*;

public class ListInserter{

       public static void insert(List list,int data){

              ListIterator it=list.listIterator();

              while(it.hasNext())     {

                     Integer in=(Integer)it.next();

                     if(data<=in.intValue()){

                            it.previous();

                            it.add(new Integer(data));

                            break;

                     }

              }

       }

    public static void main(String args[]){

              List list=new LinkedList();

              list.add(new Integer(3));

              list.add(new Integer(2));

              list.add(new Integer(5));

              list.add(new Integer(9));

              Collections.sort(list);

              insert(list,6);

              ListIterator it=list.listIterator();

              while(it.hasNext()){

                     Integer elem=(Integer)it.next();

                     System.out.println(elem+"");

              }

       }

}

实例6 比较java数组和各种List的性能

PerformanceTester.java

package collection;

import java.util.*;

public class PerformanceTester{

       private static final int TIMES=100000;

       public static abstract class Tester    {

              private String operation;

              public Tester(String operation){this.operation=operation;}

              public abstract void test(List list);

              public String getOperation(){return operation;}

       }

       static Tester iterateTester=new Tester("iterate"){

              public void test(List list){

                     for(int i=0;i<10;i++){

                            Iterator it=list.iterator();

                            while(it.hasNext())

                            {it.next();}

                     }

              }

       };

       static Tester getTester=new Tester("get"){

              public void test(List list)   {

                     for(int i=0;i<list.size();i++)

                      for(int j=0;j<10;j++)

                         list.get(j);

              }

       };

       static Tester insertTester=new Tester("insert"){

              public void test(List list)   {

                     ListIterator it=list.listIterator(list.size()/2);

                     for(int i=0;i<TIMES/2;i++)

                     it.add("hello");

              }

       };

       static Tester removeTester=new Tester("remove")

       {

              public void test(List list)

              {

                     ListIterator it=list.listIterator();

                     while(it.hasNext())

                     {

                            it.next();

                            it.remove();

                     }

              }

       };

       static public void testJavaArray(List list)     {

              Tester[]testers={iterateTester,getTester};

              test(testers,list);

       }

       static public void testList(List list){

              Tester[]testers={insertTester,iterateTester,removeTester};

              test(testers,list);

       }

       static public void test(Tester[]testers,List list){

              for(int i=0;i<testers.length;i++){

                     System.out.print(testers[i].getOperation()+"操作:");

                     long t1=System.currentTimeMillis();

                     testers[i].test(list);

                     long t2=System.currentTimeMillis();

                     System.out.println(t2-t1+"ms");

                     System.out.println();

              }

       }

       public static void main(String args[]){

              List list=null;

              System.out.println("---测试java数组---");

              String ss[]=new String[TIMES];

              Arrays.fill(ss,"hello");

              list=Arrays.asList(ss);

              testJavaArray(list);

              ss=new String[TIMES/2];

              Collection col=Arrays.asList(ss);

              System.out.println("---测试Vector---");

              list=new Vector();

              list.addAll(col);

              testList(list);

              System.out.println("---测试LinkedList---");

              list=new LinkedList();

              list.addAll(col);

              testList(list);

              System.out.println("---测试ArrayList---");

              list=new ArrayList();

              list.addAll(col);

              testList(list);

       }

}

  从结果可以看出,对java数组进行随机访问和迭代操作具有最快的速度;对LinkedList进行插入和删除具有最快的速度;对ArrayList进行随机访问也具有较快的速度,Vector类在各个方面都没有突出的性能描述与历史集合类,已经不提倡使用它。

Map

Map(映射)是一种把键对象和值对象进行映射的集合。它的每一个元素都包含一对键对象和值对象,而值对象仍可以是Map类型。以此类推,这样就形成了多级映射。向Map集合中加入元素,必须提供一对键对象和值对象,从Map集合上检索元素只要给出键对象,就会返回对应的值对象。

HashMap

HashMap类按照哈希算法存取Map中的对象,允许存储空对象,而且键是空

实例7    Statistics.java

package collection;

import java.util.HashMap;

import java.util.Map;

import java.util.Random;

class Counter{

       int i=1;

       public String toString(){

              return Integer.toString(i);

       }

}

public class Statistics{

       private static Random rand=new Random();

       public static void main(String args[]){

              Map hm=new HashMap();

              for(int i=0;i<1000;i+=1){

                 Integer r=new Integer(rand.nextInt(20));

                 if(hm.containsKey(r))

                 ((Counter)hm.get(r)).i++;

                 else

                 hm.put(r,new Counter());

          }

          System.out.println(hm);

    }

}

Hashtable

Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可以作为key或者value

实例8    HashTable.java

import java.util.Enumeration;

import java.util.Hashtable;

public class HashTable{

       public static void main(String args[]){

              String names[]={"张三","李四","王五","赵六","陈七","孙九"};

              float diameters[]={4800f,12103.6f,12756.3f,6794f,142984f,120536f};

              Hashtable hash=new Hashtable();

              for(int i=0,n=names.length;i<n;i++){

                     hash.put(names[i],new Float(diameters[i]));

              }

              Enumeration e=hash.keys();

              Object obj;

              while(e.hasMoreElements()){

                     obj=e.nextElement();

                     System.out.println(obj+":"+hash.get(obj));

              }

       }

}

HashMapHashTable的区别

HashTable继承自Dictionary,而HashMapMap interface的一个实现

HashMap允许将null作为一个key或者value,而HashTable不允许。

还有就是,HashMapHashTablecontains方法去掉了,才成containsvaluecontainsKey

最大的不同是,HashTable的方法是synchronize的,而HashMap不是,在多个线程访问HashTable时,不需要自己为它的方法实现同步而HashMap就必须为之提供外同步。

TreeMap

实例9  SortTreeMap.Java

package collection;

import java.util.Iterator;

import java.util.Map;

import java.util.TreeMap;

public class SortTreeMap{

       public static void main(String args[])   {

              String names[]={"B","E","A","M","J","C","H","D","G"};

              float diameters[]={4800f,12103.6f,12756.3f,6794f,142984f,120536f,51118f,49532f,2274f};

              Map map=new TreeMap();

              for(int i=0,n=names.length;i<n;i++){

                     map.put(names[i],new Float(diameters[i]));

              }

              Iterator it=map.keySet().iterator();

              Object obj;

              while(it.hasNext()){

                     obj=it.next();

                     System.out.println(obj+":"+map.get(obj));

              }

       }

}

二.  集合实用类:Collections

java集合中,有一个使用类,即java.util.Collections,它的一部分方法专门用于操作List类型集合,还有一部分方法用于操纵所有的Collection类型或map类型的集合。

以下方法适用于Collection类型或者map类型的集合。

实例10  Collection.java

package collection;

import java.util.*;

public class collection{

       public static void main(String args[])   {

              ArrayList arrayList1=new ArrayList();

              arrayList1.add(new Integer(1));

              arrayList1.add(new Integer(9));

              arrayList1.add(new Integer(3));

              arrayList1.add(new Integer(7));

              arrayList1.add(new Integer(8));

              arrayList1.add(new Integer(2));

              arrayList1.add(new Integer(5));

              arrayList1.add(new Integer(4));

              arrayList1.add(new Integer(6));

              System.out.println("目前ArrayList数据内容如下");

              System.out.println("arrayList1");

              Collections.sort(arrayList1);

              System.out.println("排序后的内容如下:"+arrayList1);

              Collections.reverse(arrayList1);

              System.out.println("反排序的内容如下:"+arrayList1);

              Collections.shuffle(arrayList1);

              System.out.println("重新洗牌后数据内容如下:"+Collections.max(arrayList1));

              System.out.println("最大值"+Collections.max(arrayList1));

              System.out.println("最小值"+Collections.min(arrayList1));

       }

}

三.  集合类中排序

jdk类库中,有一部分类实现了Comparable接口,如IntegerDoubleString等。Comparable接口有一个compareToObject o)方法,它返回整数类型。对于表达数x.compareTo(y),如果返回值为0,则表示xy相等,如果返回值大于0,则表示x大于y,如果返回小于0,则表示x小于y

TreeSet对象调用compareTo()方法比较及各种对象的大小。

实例11

package collection;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collection;

import java.util.Comparator;

import java.util.List;

public class ComparatorTest implements Comparable{

       String firstName,lastName;

       public Person(String f,String l){

              this.firstName=f;

              this.lastName=l;

       }

       public String getFirstName(){

              return firstName;

       }

       public String getLastName(){

              return lastName;

       }

       public String toString(){

              return "[name="+firstName+",name="+lastName+"]";

       }

       public int compareTo(Object obj){

              Person emp=(Person)obj;

              int deptComp=firstName.compareTo(emp.getFirstName());

              return((deptComp==0)?lastName.compareTo(emp.getLastName()):deptComp);

       }

       public boolean equals(Object obj){

              if(!(obj instanceofPerson)){

                     return false;

              }

              Person emp=(Person)obj;

              return firstName.equals(emp.getFirstName())&&lastName.equals(emp.getLastName());

       }

}

public class ComparatorTest implements Comparator

{

       public int compare(Object obj1,Object obj2){

              Person emp1=(Person)obj1;

              Person emp2=(Person)obj2;

              int nameComp=emp1.getFirstName().compareTo(emp2.getFirstName());

              return ((nameComp=0)?emp1.getLastName().compareTo(emp2.getLastName()):nameComp);

       }

       public static void main(String args[]){

              String name[]={"张三","李四","王五","赵六","陈七","孙八","周九"};

             

              //Convert to list

              List list=new ArrayList(Array.asList(names));

             

              //Ensure list sorted

              Collections.sort(list);

              System.out.println("List排序:[length:"+list.size()+"]");

              System.out.println(list);

             

              //Search for element in list

              int index=Collections.binarySearch(list,"李四");

              System.out.println("发现位置"+index);

 

              //Search for element not in list

              index=Collections.binarySearch(list,",楚一");

              System.out.println("没有发现楚一"+index);

 

              //insert

              int newIndex=-index-1;

              list.add(newIndex,"冯二");

              System.out.println("增加了冯二:[length:"+list.size()+"]");

              System.out.println(list);

             

              //Min should be Bart

              System.out.println(Collections.min(list));

             

              //Max should be Roy

              System.out.println(Collections.max(list));

             

              Comparator comp=Collections.reverseOrder();

             

              //Reversed Min should be Roy

              System.out.println(Collections.min(list,comp));

             

              //Reversd Max should be Bart

              System.out.println(Collections.max(list,comp));

       }

}

四.  集合类历史

 

在早期jdk1.0版本中,代表集合的类只有VectorStackEnumerationHashtableProperties。从jdk1.2版本中开始,才出现了Collectionsetlistmap接口以及各种实现类。他们构成了完整的集合框架。JDK1.0版本中的集合类也成为历史集合类

 

历史集合类

历史集合类

描述

缺点

新框架集合类的替代类

Vector

集合类中的元素有索引位置,在新的集合框架中把它改为实现了List接口

采用了同步机制,影响操纵集合的性能

ArrayListLinkedList

Stack

表示堆栈,支持后进先出的操作

采用了同步机制,影响操纵集合的性能:Stack继承了Vector类,使得Stack不能作为严格的堆栈,还允许随机访问

LinkedList

Hashtable

集合中的每一个元素包含一对键与值。在新的集合框架中把它改为实现了Map接口

采用了同步机制,影响了操纵集合的性能

HashMap

Properties

集合中的每个元素包含了一对键与值,继承了Hashtable

采用了同步机制,影响了操纵集合的性能

Enumeration

用于遍历集合中元素

只能与VectorHashtable等历史集合配套使用Enumeration类的名字较长,没有Iterator类名简短

Iterator

JDK1.2版本开始,对HashtableVector做了修改,是他们分别实现了ListMap接口。尽管如此,由于Vector StackEnumerationHashtable,在实现中使用了同步机制,并发性能差,因此不提倡使用它们,Properties类是一种特殊的Map类,他继承了HashtableObjectObject)类。Properties类的load()方法可用来从输入流中中读取键与值

 

实例 12 

myapp.properties

color=red

shape=circle

user=Tom

PropertiesTester.java

package collection;

import java.util.*;

import  java.io.*;

public class PropertiesTester{

       public static void print(Properties ps){

              Set keys=ps.keySet();

              Iterator it=keys.iterator();

              while(it.hasNext()){

                     String key=(String)it.next();

                     String value=ps.getProperty(key);

                     System.out.println(key+"="+value); 

              }

       }

       public static void main(String args[])throws IOException{

              Properties ps=new Properties();

              InputStream in=PropertiesTester.class.getResourceAsStream("myapp.properties");

              ps.load(in);

              print(ps);

              ps=System.getProperties();

              print(ps);

       }

}

五.  小结

 我们介绍了集中常用java集合类的特点点和使用方法,为了保证集合正常工作,有些集合类对存放的对象有特殊要求:

HashSet HashMap具有好的性能,是SetMap首选的实现类,是有在需要排序的场合,才考虑用TreeSetTreeMapLinkedListArrayList各有优缺点,如果经常对元素之间插入和删除操作,那么可用LinkedList,如果经常随机访问元素,那么可用ArrayList

六.  课后习题

1.       SetList有哪些区别?

2.       CollectionCollections 有什么区别?

3.       比较java数组,ArrayListLinkedList在查询和存取元素方面的性能

4.       HashMapHashTable的区别?

5.       编写一个程序,读取一系列名字,并将他们存储在LinkedList中,不能存储重复的名字,并允许用户查找一个名字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值