Java中的集合

以下内容引用自http://wiki.jikexueyuan.com/project/java/collections.html

Java 2之前,Java为对象组的存储和操作提供了特别的类比如字典(Dictionary)向量(Vector)堆栈(Stack)属性(Properties)。尽管这些类确实有用,它们缺少一个中心的,统一的主题。因此,使用向量的方法和使用属性的方法是不同的。

集合框架被设计来满足几个目标

  • 框架需要是高性能的。基础集合(动态数组,链表,树和哈希表)是高效的。
  • 框架需要允许不同的集合类型以类似的方式和高度的互操作性工作。
  • 扩展或者调整集合必须是简单的。

为此,整个集合框架被设计围绕一系列的标准接口。几个接口的标准实现例如LinkedList, HashSet和TreeSet被提供,如果选择的话,可以使用,也可以实现自己的集合。

一个集合框架是一个统一的体系结构表示和操作集合。所有的集合框架包含以下:

  • 接口:这些是代表集合的抽象数据类型。接口允许集合独立操作它们表示的细节。在面向对象的语言中,接口通常形成一个层次结构。
  • 实现,即类:这些是集合接口的具体实施。从本质上说,它们是可重用的数据结构。
  • 算法:这些是在实现集合接口的对象上进行有用计算的方法,比如搜索和排序。算法被称为多态的,那就是说,同一个方法能被用在许多不同的合适的集合接口的实现上。

除了集合,框架定义了几个Map接口和类Maps存储键值对。尽管Maps不是正确使用集合的术语,但是他们完全由集合整合起来。

一、Collection接口

集合框架定义了几个接口。如下提供了每个接口的概览:

接口描述
Collection Interface 可以使用对象组;它是集合层次阶段的顶端
List Interface 它继承了Collection并且List的一个实例存储了元素的一个有序集合
Set 它继承了Collection来处理集,它必须含有特殊的元素
SortedSet 它继承了Set来处理 排序的 set
Map 它将独特的键和值匹配
Map Entry 这描述了映射中的一个元素(一个键值对)。它是Map的一个内部类。
SortedMap 它继承了Map因此键按升序保持
Enumeration 它是旧有的接口并定义了在对象的集合中列举(一次获得一个)元素的方法。这个旧有的接口被迭代器取代了。

二、Collection类

Java提供了一系列的实现集合接口的标准集合类。一些类提供了完全的能被直接使用的实现,其他就是抽象类,提供的被用来作为创建具体集合的实现。

标准的Collection类在下面的表格中被概括:

描述
AbstractCollection 实现大部分的Collection接口
AbstractList 继承AbstractCollection并且实现大部分List接口
AbstractSequentialList 通过一个使用有序的而不是随机访问它的元素的集合继承AbstractList
LinkedList 通过继承AbstractSequentialList实现一个链表
ArrayList  通过继承AbstractList实现一个动态数组
AbstractSet 继承AbstractCollection并实现大部分的Set接口
HashSet 用一个哈希表继承AbstractSet
LinkedHashSet 继承HashSet来允许插入顺序迭代
TreeSet 实现在树中存储的一个集。继承AbstractSet
AbstractMap 实现大部分的Map接口
HashMap 用一个哈希表继承AbstractMap
TreeMap 用一棵树继承AbstractMap
WeakHashMap 用一个使用弱键的哈希表来继承AbstractMap
LinkedHashMap 继承AbstractMap来允许插入顺序迭代
IdentityHashMap 继承AbstractMap类并且当比较文档时平等使用参考

AbstractCollection,AbstractSet,AbstractList,AbstractSequentialList和AbstractMap类提供了核心集合接口的实现,尽量减少努力来实现它们。

以下的由java.util定义的类:

描述
Vector 这实现一个动态数组。它和ArrayList类似,但也有一些不同。
Stack Stack是Vector的实现标准的后进先出栈的子类
Dictionary 是一个抽象的代表一个键值对存储库的类并且操作起来非常像Map
Hashtable Hashtable是初始的java.util的一部分并且是Dictionary的具体实现
Properties Properties是Hashtable的一个子类。它被用来保持键是一个字符串并且值也是一个字符串的值的列表
BitSet 一个BitSet类创建一个特殊的保持bit数值的数组类型。这个数组的大小能根据需要增长

三、Collection算法

集合框架定义了几个能被应用到Collections和Maps的算法。这些算法在Collection类的内部被定义为静态方法。

几个方法能抛出异常ClassCastException,它发生在想要比较不兼容的类型时;或者异常UnsupportedOperationException,它发生在想要修改一个不能修改的集合时。

集合定义了三个静态变量:EMPTY_SET,EMPTY_LIST和EMPTY_MAP。所有都是不变的。

收集框架算法中定义的方法总结在下表中:

方法说明
static int binarySearch(List list, Object value, Comparator c)

根据c.搜索列表中的价值。返回列表中的值的位置,如果未找到值,则返回-1。

static int binarySearch(List list,Object value)

搜索列表中的值。列表必须排序。返回列表中的值的位置,如果未找到值,则返回-1。


static void copy(List list1, List list2)

将list2的元素复制到list1。

static Enumeration enumeration(Collection c)

返回c的枚举。

static void fill(List list, Object obj)

将obj分配给列表的每个元素。

static int indexOfSubList(List list, List subList)

子列表首次出现的搜索列表。返回第一个匹配的索引,如果没有找到匹配,则返回.1。

static int lastIndexOfSubList(List list, List subList)

子列表最后一次出现的搜索列表。返回上一个匹配的索引,如果没有匹配,则返回.1。

static ArrayList list(Enumeration enum)

返回一个包含枚举元素的ArrayList。

static Object max(Collection c, Comparator comp)

返回由comp确定的c中的最大元素。

static Object max(Collection c)

返回c中的最大元素,由自然排序确定。集合不需要排序。

static Object min(Collection c, Comparator comp)

返回由comp确定的c中的最小元素。集合不需要排序。

static Object min(Collection c)

返回由自然排序确定的c中的最小元素。

static List nCopies(int num, Object obj)

返回包含在不可变列表中的对象的num副本。num必须大于或等于零。

static boolean replaceAll(List list, Object old, Object new)

在列表中替换所有出现的旧版本。如果至少有一个替换发生,则返回true。返回false,否则。

static void reverse(List list)

反转列表中的序列。

static Comparator reverseOrder( )

返回反向比较器。

static void rotate(List list, int n)

将列表旋转到右侧的n个位置。要向左旋转,请对n使用负值。

static void shuffle(List list, Random r)

通过使用r作为随机数的来源来洗牌(即随机化)列表中的元素。

static void shuffle(List list)

洗牌(即随机化)列表中的元素。

static Set singleton(Object obj)

将obj作为不可变集返回。这是将单个对象转换为集合的简单方法。

static List singletonList(Object obj)

将obj作为不可变列表返回。这是将单个对象转换为列表的简单方法。

static Map singletonMap(Object k, Object v)

返回键/值对k / v作为不可变地图。这是将单个键/值对转换为地图的简单方法。

static void sort(List list, Comparator comp)

对由comp确定的列表元素进行排序。

static void sort(List list)

根据其自然排序确定列表的元素。

static void swap(List list, int idx1, int idx2)

以idx1和idx2指定的索引交换列表中的元素。

static Collection synchronizedCollection(Collection c)

返回由c支持的线程安全集合。

static List synchronizedList(List list)

返回由列表支持的线程安全列表。

static Map synchronizedMap(Map m)

返回由m支持的线程安全映射。

static Set synchronizedSet(Set s)

返回由s支持的线程安全集。

static SortedMap synchronizedSortedMap(SortedMap sm)

返回由sm支持的线程安全排序集。

static SortedSet synchronizedSortedSet(SortedSet ss)

返回由ss支持的线程安全集。

static Collection unmodifiableCollection(Collection c)

返回由c支持的不可修改的集合。

static List unmodifiableList(List list)

返回列表支持的不可修改列表。

static Map unmodifiableMap(Map m)

返回由m支持的不可修改的地图。

static Set unmodifiableSet(Set s)

返回由s支持的不可修改的集合。

static SortedMap unmodifiableSortedMap(SortedMap sm)

返回由sm支持的不可修改的排序映射。

static SortedSet unmodifiableSortedSet(SortedSet ss)

返回由ss支持的不可修改的排序集。

示例:

以下是一个示例,其演示了各种算法。

import java.util.*;
public class AlgorithmsDemo {

   public static void main(String args[]) {
      
      // Create and initialize linked list
      LinkedList ll = new LinkedList();
      ll.add(new Integer(-8));
      ll.add(new Integer(20));
      ll.add(new Integer(-20));
      ll.add(new Integer(8));
      
      // Create a reverse order comparator
      Comparator r = Collections.reverseOrder();
      
      // Sort list by using the comparator
      Collections.sort(ll, r);
      
      // Get iterator
      Iterator li = ll.iterator();
      System.out.print("List sorted in reverse: ");
      
      while(li.hasNext()) {
         System.out.print(li.next() + " ");
      }
      System.out.println();
      Collections.shuffle(ll);
      
      // display randomized list
      li = ll.iterator();
      System.out.print("List shuffled: ");
      
      while(li.hasNext()) {
         System.out.print(li.next() + " ");
      }

      System.out.println();
      System.out.println("Minimum: " + Collections.min(ll));
      System.out.println("Maximum: " + Collections.max(ll));
   }
}
//这将产生以下结果
List sorted in reverse: 20 8 -8 -20
List shuffled: 20 -20 8 -8
Minimum: -20
Maximum: 20

四、如何使用Iterator(迭代器)

通常,想要在集合中循环元素。比如,可能想要显示每个元素。

这么做最简单的方法是使用Iterator,它是一个实现或者是Iterator或者ListIterator接口的对象。

Iterator可以通过一个集合循环,获得或者除去元素。ListIterator继承了Iterator来允许一个列表的双向遍历和元素的修改。

在通过Iterator访问集合之前,必须先获取一个集合。每个集合类都提供了一个iterator()方法,它将Iterator返回到集合的开头。通过使用此Iterator对象,可以一次访问集合中的每个元素,或者一个元素。

一般来说,要使用Iterator循环遍历集合的内容,请按照下列步骤操作:

  • 通过调用集合的iterator()方法获取集合开始的Iterator。

  • 设置一个调用hasNext()的循环。只要hasNext()返回true,循环迭代。

  • 在循环中,通过调用next()来获取每个元素。

对于实现List的集合,还可以通过调用ListIterator获取Iterator。

迭代器(Iterator)声明的方法:

方法说明
boolean hasNext( )

如果有更多元素,则返回true。否则返回false。

Object next( )

返回下一个元素。如果没有下一个元素,则抛出NoSuchElementException异常。

void remove( )

删除当前元素。如果尝试调用remove()之前未调用next(),则抛出IllegalStateException异常。

ListIterator声明的方法:

方法说明
void add(Object obj)

将obj插入到下一次调用next()返回的元素前面的列表中。

boolean hasNext( )

如果有下一个元素,则返回true。否则返回false。

boolean hasPrevious( )

如果存在先前的元素,则返回true。否则返回false。

Object next( )

返回下一个元素。如果没有下一个元素,则抛出NoSuchElementException异常。

int nextIndex( )

返回下一个元素的索引。如果没有下一个元素,则返回列表的大小。

Object previous( )

返回上一个元素。如果没有先前的元素,则抛出NoSuchElementException异常。

int previousIndex( )

返回上一个元素的索引。如果没有以前的元素,返回-1。

void remove( )

从列表中删除当前元素。如果在调用next()或previous()之前调用remove(),则抛出IllegalStateException异常。

void set(Object obj)

将obj分配给当前元素。这是通过调用next()或previous()最后返回的元素。

示例:

下面是一个演示Iterator和ListIterator的例子。它使用一个ArrayList对象,但一般原则适用于任何类型的集合。

当然,ListIterator仅适用于实现List接口的那些集合。

import java.util.*;
public class IteratorDemo {

   public static void main(String args[]) {
      // Create an array list
      ArrayList al = new ArrayList();
      
      // add elements to the array list
      al.add("C");
      al.add("A");
      al.add("E");
      al.add("B");
      al.add("D");
      al.add("F");

      // Use iterator to display contents of al
      System.out.print("Original contents of al: ");
      Iterator itr = al.iterator();
      
      while(itr.hasNext()) {
         Object element = itr.next();
         System.out.print(element + " ");
      }
      System.out.println();
      
      // Modify objects being iterated
      ListIterator litr = al.listIterator();
      
      while(litr.hasNext()) {
         Object element = litr.next();
         litr.set(element + "+");
      }
      System.out.print("Modified contents of al: ");
      itr = al.iterator();
      
      while(itr.hasNext()) {
         Object element = itr.next();
         System.out.print(element + " ");
      }
      System.out.println();

      // Now, display the list backwards
      System.out.print("Modified list backwards: ");
      
      while(litr.hasPrevious()) {
         Object element = litr.previous();
         System.out.print(element + " ");
      }
      System.out.println();
   }
}
//这将产生以下结果:
Original contents of al: C A E B D F
Modified contents of al: C+ A+ E+ B+ D+ F+
Modified list backwards: F+ D+ B+ E+ A+ C+

五、如何使用Comparator(比较器)

TreeSet和TreeMap都以顺序保存元素。然而,是Comparator精确定义排序。

这个接口将一个给定的集合用不同数量的方法排序。这个接口也能被用来排列任何类的任何实例(甚至是不能修改的类)。

比较器接口定义了两种方法:compare()和equals()。

compare()方法,如下所示,比较了两个元素的顺序:

比较方法:

int compare(Object obj1, Object obj2)

obj1和obj2是要进行比较的对象。如果对象相等,则此方法返回零。如果obj1大于obj2,则返回正值。否则返回负值。

通过重写compare(),可以改变对象的排序方式。例如,要按相反顺序进行排序,可以创建一个比较器来反转比较结果。

等于方法:

这里显示的equals()方法测试对象是否等于调用比较器

boolean equals(Object obj)

obj是要进行相等测试的对象。如果obj和调用对象都是Comparator对象并使用相同的顺序,则该方法返回true。否则返回false。

覆盖equals()是不必要的,大多数简单的比较器都不会这样做。

示例:

import java.util.*;

class Dog implements Comparator<Dog>, Comparable<Dog> {
   private String name;
   private int age;
   Dog() {
   }

   Dog(String n, int a) {
      name = n;
      age = a;
   }

   public String getDogName() {
      return name;
   }

   public int getDogAge() {
      return age;
   }

   // Overriding the compareTo method
   public int compareTo(Dog d) {
      return (this.name).compareTo(d.name);
   }

   // Overriding the compare method to sort the age 
   public int compare(Dog d, Dog d1) {
      return d.age - d1.age;
   }
}

public class Example {

   public static void main(String args[]) {
      // Takes a list o Dog objects
      List<Dog> list = new ArrayList<Dog>();

      list.add(new Dog("Shaggy", 3));
      list.add(new Dog("Lacy", 2));
      list.add(new Dog("Roger", 10));
      list.add(new Dog("Tommy", 4));
      list.add(new Dog("Tammy", 1));
      Collections.sort(list);   // Sorts the array list

      for(Dog a: list)   // printing the sorted list of names
         System.out.print(a.getDogName() + ", ");

      // Sorts the array list using comparator
      Collections.sort(list, new Dog());
      System.out.println(" ");
      
      for(Dog a: list)   // printing the sorted list of ages
         System.out.print(a.getDogName() +"  : "+ a.getDogAge() + ", ");
   }
}
//这将产生以下结果:
Lacy, Roger, Shaggy, Tammy, Tommy,
Tammy  : 1, Lacy  : 2, Shaggy  : 3, Tommy  : 4, Roger  : 10,

六、总结

Java集合框架给了程序员打包数据结构和操作它们的算法的入口。

一个集合是一个能对其他对象引用的对象。Collection接口声明了能在每一个集合类型上操作的操作。

集合框架的类和接口都在java.util包内。

 

测试工程:https://github.com/easonjim/5_java_example/tree/master/javabasicstest/test23/test1

posted @ 2017-06-03 16:34  EasonJim  阅读(298)  评论(0编辑  收藏  举报