提交 f5124f16 编写于 作者: A Allenyep

3th

上级 936e8325
......@@ -166,4 +166,143 @@ public static boolean subsetOf (Collection<?> C0, Collection<?> C1) {
// ...
return true;
}
```
\ No newline at end of file
```
我们不知道C0和C1是什么类型的对象(它们可能是完全不同的Collection实现类),也不清楚他们的迭代器以什么顺序提供元素,是否允许重复。这些方法仅依赖于接口及其注释中描述的属性,并且总是能达到想要的效果(假如这些程序员是通过实现Collection去完成他们的工作)。
``` java
package java.util;
/** A collection of values, each an Object reference. */
public interface Collection<T> extends Iterable<T> {
/* Constructors. Classes that implement Collection should* have at least two constructors:* CLASS (): Constructs an empty CLASS* CLASS (C): Where C is any Collection, constructs a CLASS that* contains the same elements as C. *//* Required met hods: *//** The number of values in THIS. */
int size ();
/** True iff size () == 0. */
boolean isEmpty ();
/** True iff THIS contains X: that is, if for some z in* THIS, either z and X are null, or z.equals (X). */
boolean contains (Object x);
/** True iff contains(x) for all elements x in C. */
boolean containsAll (Collection<?> c);
/** An iterator that yields all the elements of THIS, in some* order. */
Iterator<T> iterator ();
/** A new array containing all elements of THIS. */
Object[] toArray ();
/** Assuming ANARRAY has dynamic type T[] (where T is some* reference type), the result is an array of type T[] containing* all elements of THIS. The result is ANARRAY itself, if all of* these elements fit (leftover elements of ANARRAY are set to null).* Otherwise, the result is a new array. It is an error if not* all items in THIS are assignable to T. */
<T> T[] toArray (T[] anArray);
// Interface java.util.Collection, continued.
/* Optional methods. Any of these may do nothing except to* throw UnsupportedOperationException. */
/** Cause X to be contained in THIS. Returns true if the Collection *
/* changes as a result. */
boolean add (T x);
/** Cause all members of C to be contained in THIS. Returns true* if the object THIS changes as a result. */
boolean addAll (Collection<? extends T> c);
/** Remove all members of THIS. */
void clear ();
/** Remove a Object .equal to X from THIS, if one exists,* returning true iff the object THIS changes as a result. */
boolean remove (Object X);
/** Remove all elements, x, such that C.contains(x) (if any* are present), returning true iff there were any* objects removed. */
boolean removeAll (Collection<?> c);
/** Intersection: Remove all elements, x, such that C.contains(x)* is false, returning true iff any items were removed. */
boolean retainAll (Collection<?> c);}
```
代码2.5 接口java.util.Collection。必须方法和可选方法。
### 2.2.2 Set接口
在数学中,集合是没有重复的值的集合。这也是接口java.util.Set的定义。然而这个规定并不是以Java接口的形式直接表达的。实际上就Java编译器而言,以下是一个非常好的定义:
``` java
package java.util;
public interface Set<T> extends Collection<T> { }
```
这些方法都是一样的。它们的不同之处都在注释中。各元素的单拷贝规则在几个方法中更具体的注释中反映出来。结果如代码2.7所示。在这个定义中,我们还包括equals和hashCode方法。这些方法自动成为任何接口的一部分,因为它们是在Java类java.lang.Object中定义的,但我把它们包含在这里是因为它们的语义规范(注释)比一般对象更严格。当然,equals是来表示集合相等。我们将在第7章详解hashCode。
### 2.2.3 List接口
由于该术语是在Java库中使用的,list是有序元素集合,可能具有重复元素。也就是说,它是一种特殊的Collection,其中有一个元素的序列,第一个元素,最后一个元素,第n个元素,并且其中元素可能出现重复(和Set不一样)。因此,包含对有序序列的其他方法的扩展接口(相对于Collection)是有意义的。代码2.8展示了该接口。
大量方法包含在listIterator类及其返回的对象中。从接口描述中可以看到,可以使用列表(List)接口本身的方法插入、添加、删除或排序列表中的项。或者你也可以通过使用listIterator创建一个列表迭代器。使用listIterator来处理整个列表(或其中的某些部分)通常比使用List和其他List的方法更快,它使用数字索引来表示需要的元素。
**视图**
subList方法十分特别。诸如L.subList(i,j)的调用通过返回值以产生另一个List(通常与L不同),它由L的(j-1)个项组成。此外,它是通过提供L的这一部分的视图来实现的,即访问相同数据容器的另一种方式。这个设计思路是修改子列表(使用添加,删除和设置等方法)也应该修改L的相应部分。例如,要删除列表L中除第一个k项以外的所有项,您可以编写
``` java
L.subList (k, L.size ()).clear ();
```
``` java
package java.util;
/** A Collection that contains at most one null item and in which no* two distinct non-null items are .equal. The effects of modifying* an item contained in a Set so as to change the value of .equal* on it are undefined. */
public interface Set<T> extends Collection<T> {
/* Constructors. Classes that implement Set should* have at least two constructors:* CLASS (): Constructs an empty CLASS* CLASS (C): Where C is any Collection, constructs a CLASS that* contains the same elements as C, with duplicates removed. */
/** Cause X to be contained in THIS. Returns true iff X was *
/* not previously a member. */
boolean add (T x);
/** True iff S is a Set (instanceof Set) and is equal to THIS as a* set (size()==S.size() each of item in S is contained in THIS). */
boolean equals (Object S);
/** The sum of the values of x.hashCode () for all x in THIS, with* the hashCode of null taken to be 0. */
int hashCode ();
/* Other methods inherited from Collection:* size, isEmpty, contains, containsAll, iterator, toArray,* addAll, clear, remove, removeAll, retainAll */
}
```
代码2.7 接口java.util.Set.只展示比Collection更具体的注释的方法。
``` java
package java.util;
/** An ordered sequence of items, indexed by numbers 0 .. N-1,* where N is the size() of the List. */
public interface List<T> extends Collection<T> {
/* Required metho ds: *//** The Kth element of THIS, where 0 <= K < size(). Throws* IndexOutOfBoundsException if K is out of range. */
T get (int k);
/** The first value k such that get(k) is null if X==null,* X.equals (get(k)), otherwise, or -1 if there is no such k. */
int indexOf (Object x);
/** The largest value k such that get(k) is null if X==null,* X.equals (get(k)), otherwise, or -1 if there is no such k. */
int lastIndexOf (Object x);
/* NOTE: The methods iterator, listIterator, and subList produce* views that become invalid if THIS is structurally modified by* any other means (see text). */
/** An iterator that yields all the elements of THIS, in proper* index order. (NOTE: it is always valid for iterator() to* return the same value as would listIterator, below.) */
Iterator<T> iterator ();
/** A ListIterator that yields the elements K, K+1, ..., size()-1* of THIS, in that order, where 0 <= K <= size(). Throws* IndexOutOfBoundsException if K is out of range. */
ListIterator<T> listIterator (int k);
/** Same as listIterator (0) */
ListIterator<T> listIterator ();
/** A view of THIS consisting of the elements L, L+1, ..., U-1,* in that order. Throws IndexOutOfBoundsException unless* 0 <= L <= U <= size(). */
List<T> subList (int L, int U);
/* Other methods inherited from Collection:* add, addAll, size, isEmpty, contains, containsAll, remove, toArray */
```
代码2.8 接口java.util.List的方法,以及从Collection继承的方法
因此,List上有很多的操作,不需要定义就能使用,因为它是对子列表操作的结果。例如不需要手写从i到j删除的remove方法,或者通过索引搜索下标k的元素的indexOf方法。
迭代器(包括ListIterators)提供了另一个视图集合的示例。同样可以通过其方法提供的迭代器访问或修改Collection的当前内容。就此而言,任何Collect都可以是一个视图 - “身份视图”。
每当同一实体有两个可能的视图时,使用其中一个来修改实体会有可能干扰另一个视图。在一个视图中的变化不仅仅是原视图中,应该在其他视图中看到(如上面清除子列表的示例),但是当被查看的实体被其他方式改变时,一些视图的快速直接实现可能会出错。在迭代器上调用remove方法时应该发生什么,根据Iterator的规范,应该删除的元素是否已经被直接删除(通过在完整的Collection上调用remove方法)。假设有一个包含某些完整List元素2到4的子列表。如果清除完整List,然后添加3个元素,子列表视图中的内容是什么?
由于存在这些问题,通过除该视图之外的某些方式,其生成方法的完整规范(在List接口中是iterator,listIterator和subList)都规定,如果基础List在结构上进行了修改(如果添加或删除了元素),则视图将变为无效。因此,如果执行L.add(...),则L.iterator()的结果将变为无效,或者如果你执行从L生成的其他迭代器或子列表中的remove方法也是如此。然而,我们还会遇到一些视图,例如由Map中的值方法(参见图2.12)生成的视图,这些视图应该保持有效,即使在对象中进行结构修改时也是如此;对于Map的实现来说,设计者认为这是有必要的。
### 2.2.4 有序Set
List接口描述了描述序列的数据类型,在这些序列中,程序员通过将序列中的元素添加到序列中的顺序或位置明确地表明序列中元素的顺序。相比之下,SortedSet接口旨在描述数据根据某些选定关系确定排序的序列。当然,这里出现了一个问题:在Java中,我们如何表示这个“选定关系”,以便我们可以定义它?我们如何将排序关系作为参数?
**排序:Comparable和Comparator接口**
函数有多种方法来定义某些set对象的排序。一种方法是用具有明显的含义来定义布尔运算如equals, less, greater等。C族语言(包括Java)中的库倾向于将所有这些组合成一个单独的函数,该函数用整数返回值表示关系。例如,在String类型上,x.compareTo("cat")返回一个零,负或正整数,具体取决于x是否等于“cat”,是否以词典顺序出现在它之前,或者在它之后出现。因此,Strings上的排序x≤y对应于条件x.compareTo(y)<= 0。
``` java
package java.lang;
/** Describes types that have a natural ordering. */public interface Comparable<T> {
/** Returns*
* a negative value iff THIS < Y under the natural ordering*
* a positive value iff THIS > Y;*
* 0 iff X and Y are "equivalent".*
Throws ClassCastException if X and Y are incomparable. */
int compareTo (T y);
}
```
代码2.9 接口java.lang.Comparable,它标记了自然排序的类。
出于SortedSet接口的目的,由compareTo方法(或者是compare)表示的此≤(或≥)排序旨在是总排序。也就是说,它是有传递性的(x≤y且y≤z意味着x≤z),自反性的(x ≤ x),反对称的(x≤y且y≤x表示x等于y)。此外,对于函数域中的所有x和y,x≤y或者y≤x。
一些类(如字符串String)定义了自己的标准比较操作。这样做的标准方法是实现Comparable接口,如代码2.9所示。然而,并非所有的类都有这样的排序,自然排序也不一定是在任何给定情况下想要的。例如,可以按字典顺序、颠倒字典顺序或不区分大小写的顺序对字符串排序。
在Scheme语言中,没有这样一个特别的问题:排序关系只是一个函数,在Schame中函数是非常好的值。在一定程度上,在C和Fortran等语言中也是如此,在这些语言中,函数可以用作子程序的参数,但Schame不同,它只能访问全局变量(Java中称为静态作用域或类变量)。Java不直接支持函数作为值,但事实证明,这不是一个限制。Java标准库将Comparator接口(图2.10)定义为可用作排序关系的表示。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册