第9章 集合(重中之重)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/NCUscienceZ/article/details/83474689

1、java迭代器:

public interface Iterator < E >
{
	E next ( ) ;
	boolean hasNextO ;
	void remove 0 ;
	default void forEachRemaining ( Consumer < ? super E > action ) ;
}

样例程序:

Collection < String > c = . . . ;
Iterator < String > iter = c.iterator();
while ( iter.hasNext())
{
	String element = iter.next();
   do something with element
}

用 “ foreach ” 循环可以更加简练地表示同样的循环操作 :

for ( String element : c )
{
	do something with element
}

2、 Iterable 接口:
编译器简单地将 “ for each ” 循环翻译为带有迭代器的循环 。
“for each ” 循环可以与任何实现了 Iterable 接口的对象一起工作 , 这个接口只包含一个
抽象方法 :

public interface Iterable < E >{
	Iterator < E > iterator() ;
}

Collection 接口扩展了 Iterable 接口。 因此 , 对于标准类库中的任何集合都可以使用 “
for each ” 循环 。

3、java集合类库的迭代器与c++STL迭代器区别:
Java 集合类库中的迭代器与其他类库中的迭代器在概念上有着重要的区别。 在传统的集合类库中,例如 , C + + 的标准模版库 , 迭代器是根据数组索引建模的 。 如果给定这样一个迭代器 ,就可以查看指定位置上的元素 , 就像知道数组索引 i 就可以査看数组元素 a [ i ] — 样 。不需要查找元素, 就可以将迭代器向前移动一个位置 。 这与不需要执行査找操作就可以通过i + + 将数组索引向前移动一样 。 但是, Java 迭代器并不是这样操作的 。 查找操作与位置变更
是紧密相连的。 查找一个元素的唯一方法是调用 next ,而在执行查找操作的同时, 迭代器的位置随之向前移动。因此, 应该将 Java 迭代器认为是位于两个元素之间 。 当调用 next 时 , 迭代器就越过下一个元素 , 并返回刚刚越过的那个元素的引用。

4、next 方法和 remove 方法的调用具有互相依赖性:
如果调用
remove 之前
没有调用 next 将是不合法的 。 如果这样做 , 将会抛出一个 IllegalStateException 异常

如果想删除两个相邻的元素 , 不能直接地这样调用 :
it . remove ( ) ;
it . remove ( ) ; / / Error !
相反地, 必须先调用 next 越过将要删除的元素 。
it , remove ( ) ;
it . next ( ) ;
it . remove ( ) ; / / OK

5、**在 Java 类库中, 集合类的基本接口是 Collection 接口 。**下面列出 Collection 接口常用的API:
java . util . Collection < E > 1.2
• Iterator < E > iterator ()
返回一个用于访问集合中每个元素的迭代器 。
•int size ()
返回当前存储在集合中的元素个数。
•boolean isEmpty ()
如果集合中没有元素 , 返回 true。
•boolean contains ( Object obj )
如果集合中包含了一个与 obj 相等的对象 , 返回 true。
•boolean containsAll ( Collection < ? > other )
如果这个集合包含 other 集合中的所有元素 , 返回 true。
•boolean add ( Object element )
将一个元素添加到集合中。 如果由于这个调用改变了集合 , 返回true 。
•boolean addAll ( Collection < ? extends E > other )
将 other 集合中的所有元素添加到这个集合。 如果由于这个调用改变了集合 , 返回true。
•boolean remove ( Object obj )从这个集合中删除等于 obj 的对象。 如果有匹配的对象被删除 , 返回true。
•boolean removeAll ( Collection < ? > other )
从这个集合中删除 other 集合中存在的所有元素。 如果由于这个调用改变了集合 , 返回 true 。
•default boolean removelf ( Predicate < ? super E > filter ) 8
从这个集合删除 filter 返回 true 的所有元素。 如果由于这个调用改变了集合 , 则返回 true 。
•void clear ( )
从这个集合中删除所有的元素 。
•boolean retainAll( Collection < ? > other )
从这个集合中删除所有与 other 集合中的元素不同的元素 。 如果由于这个调用改变了
集合 , 返回 true。
•Object [] toArray ( )
返回这个集合的对象数组。
•< T > T [] toArray ( T [] arrayToFill )
返回这个集合的对象数组。 如果 arrayToFill足够大, 就将集合中的元素填入这个数组
中。 剩余空间填补null ; 否则 , 分配一个新数组 , 其成员类型与 arrayToFill 的成员类
型相同 , 其长度等于集合的大小 , 并填充集合元素 。

6、泛形要求能包容的是对象类型,而基本类型在java里不属于对象。
但是基本类型都有其包装类型,也就是对象类型: int->Integer long->Long …

7、集合两大基本接口: Collection 和 Map。

8、java集合框架下具体的常用汇总:

ArrayList                    一种可以动态增长和缩减的索引序列
LinkedList                   一种可以在任何位置进行高效地插人和删除操作的有序序列
ArrayDeque                   一种用循环数组实现的双端队列
HashSet                      一种没有重复元素的无序集合
TreeSet                      一种有序集
EnumSet                      一种包含枚举类型值的集
LinkedHashSet                一种可以记住元素插人次序的集
PriorityQueue                一种允许高效删除最小元素的集合
HashMap                      一种存储键 / 值关联的数据结构
TreeMap                      一种键值有序排列的映射表
EnumMap						 一种键值属于枚举类型的映射表
LinkedHashMap                一种可以记住键 / 值项添加次序的映射表
WeakHashMap                  一种其值无用武之地后可以被垃圾回收器回收的映射表
IdentityHashMap              一种用 = 而不是用 equals 比较键值的映射表

9、有序集合支持顺序随机两种访问方式的List接口
java.util.List 1.2

•ListIterator < E > 1 istIterator ( )
返回一个列表迭代器, 以便用来访问列表中的元素 。
•ListIterator < E > 1 istIterator ( int index )
返回一个列表迭代器 , 以便用来访问列表中的元素 , 这个元素是第一次调用 next 返回的给定索引的元素。
•void add ( int i , E element )
在给定位置添加一个元素 。
•void addAl 1 ( int i , Col 1 ection < ? extends E > elements )
将某个集合中的所有元素添加到给定位置。
•E remove ( int i )
删除给定位置的元素并返回这个元素。
•E get ( int i )
获取给定位置的元素。
•E set ( int i , E element )
用新元素取代给定位置的元素 , 并返回原来那个元素 。
•int indexOf ( Object element )
返回与指定元素相等的元素在列表中第一次出现的位置 , 如果没有这样的元素将返回 - 1。
•int 1 astlndexOf ( Object element )
返回与指定元素相等的元素在列表中最后一次出现的位置 , 如果没有这样的元素将返
回 - 1.

10、实现了List接口的链表相关API:
java . util . Listlterator < E > 1.2

•void add ( E newElement )
在当前位置前添加一个元素。
•void set ( E newElement )
用新元素取代 next 或 previous 上次访问的元素。 如果在next 或 previous 上次调用之后列表结构被修改了, 将拋出一个IllegalStateException 异常。
•boolean hasPrevious ()
当反向迭代列表时, 还有可供访问的元素 , 返回true 。
•E previous ( )
返回前对象。 如果已经到达了列表的头部 ,就抛出一个NoSuchElementException 异常。
•int nextlndex ()
返回下一次调用 next 方法时将返回的元素索引 。
•int previousIndex ( )
返回下一次调用 previous 方法时将返回的元素索引。

java.util.LinkedList 1.2

•LinkedList ()
构造一个空链表。
• LinkedList( Collection < ? extends E > elements )
构造一个链表 , 并将集合中所有的元素添加到这个链表中。
•void addFirst ( E element )
•void addLast ( E element )
将某个元素添加到列表的头部或尾部。
•E getFirst ( )
•E getLast ( )
返回列表头部或尾部的元素 。
•E removeFirst ( )
•E removeLast ( )
删除并返回列表头部或尾部的元素 。

11、动态数组ArrayList,重点记忆其也实现了List接口。
注释 : 对于一个经验丰富的 Java 程序员来说 , 在需要动态数组时 , 可能会使用 Vector 类。
为什么要用 ArrayList 取代 Vector 呢 ? 原因很简单 : Vector 类的所有方法都是同步的。可以由两个线程安全地访问一个 Vector 对象。 但是 , 如果由一个线程访问Vector , 代码要在同步操作上耗费大量的时间。 这种情况还是很常见的 。而 ArrayList 方法不是同步的,因此, 建议在不需要同步时使用ArrayList , 而不要使用 Vector。

12、散列集合hashset相关API:
java . util . HashSet < E > 1.2

•HashSet ( )
构造一个空散列表 。
•HashSet ( Col 1 ection < ? extends E > elements )
构造一个散列集 , 并将集合中的所有元素添加到这个散列集中 。
•HashSet ( int initialCapacity )
构造一个空的具有指定容量 ( 桶数 ) 的散列集 。
•HashSet ( int initialCapacity , float loadFactor )
构造一个具有指定容量和装填因子 ( 一个 0.0 ~ 1.0 之间的数值 , 确定散列表填充的百分比
, 当大于这个百分比时 , 散列表进行再散列 ) 的空散列集 。

java . Iang . Object 1.0

•int hashCode ( )//注意这是Object对象自带的散列码生成方法,大多数与对象的存储地址有关
返回这个对象的散列码。 散列码可以是任何整数 , 包括正数或负数 。 equals 和 hashCode的定义必须兼容, 即如果 x . equals ( y ) 为 true ,x . hashCodeO 必须等于 y . hashCodeO。

13、树集TreeSet,自己习惯的c++STl中的set,是一种基于进阶二叉搜索树(红黑树)的集合。所有内部元素成功添加之后都会自动排好序。但是作为代价是,将一个元素添加到树中要比添加到散列表中慢 ,如果树中包含n 个元素 , 査找新元素的正确位置平均需要 l 0 g 2 n 次比较。 例如 ,如果一棵树包含了 1000 个元素, 添加一个新元素大约需要比较10 次。

14、 注释 : 要使用树集 , 必须能够比较元素 。 这些元素必须实现 Comparable 接口 ( 参见6.1 . 1节 ), 或者构造集时必须提供一个 Comparator( 参见 6.2 . 2 节和 6.3 . 8 节 )。

15、关于TreeSet与HashSet选择问题:
是否总是应该用树集取代散列集 。 毕竟 , 添加一个元素所花费的时间看上去并不很长, 而且元素是自动排序的 。 到底应该怎样做将取决于所要收集的数据。 如果不需要对数据进行排序 ,就没有必要付出排序的开销。 更重要的是 , 对于某些数据来说, 对其排序要比散列函数更加困难 。 散列函数只是将对象适当地打乱存放 , 而比较却要精确地判别每个对象。

16、树集TreeSet相关API:
java . util . TreeSet 1.2

• TreeSet( )
• TreeSet( Comparator < ? super E > comparator )构造一个空树集 。
• TreeSet( Collection < ? extends E > elements )
• TreeSet ( SortedSet < E > s )
构造一个树集 , 并增加一个集合或有序集中的所有元素 ( 对于后一种情况, 要使用同样的顺序 )。

java . util . SortedSet < E > 1.2

•Comparator< ? super E > comparator )
返回用于对元素进行排序的比较器。 如果元素用 Comparable 接口的 compareTo 方法进行比较则返回 null。
•E first()
•E last()
返回有序集中的最小元素或最大元素。

java . util . NavigableSet < E > 6

•E higher ( E value )
•E lower ( E value )
返回大于 value 的最小元素或小于 value 的最大元素, 如果没有这样的元素则返回 null 。
• E ceiling ( E value )
•E floor ( E value )
返回大于等于 vaiue 的最小元素或小于等于 value 的最大元素, 如果没有这样的元素则返回 null。
•E pollFirst ( )
•E pollLast
删除并返回这个集中的最大元素或最小元素 , 这个集为空时返回 null 。
• Iterator < E >descendingIterator()
返回一个按照递减顺序遍历集中元素的迭代器。

17、双端队列及相关API:
在Java SE 6 中引人了 Deque 接口 , 并由 ArrayDeque 和LinkedList 类实现。 这两个类都提供了双端队列 , 而且在必要时可以增加队列的长度 。
java . utii . Queue < E > 5.0

•boolean add ( E element )
•boolean offer ( E element )
如果队列没有满, 将给定的元素添加到这个双端队列的尾部并返回 true 。 如果队列满
了, 第一个方法将拋出一个 IllegalStateException ,而第二个方法返回 false。
•E remove ( )
•E poll ( )
假如队列不空, 删除并返回这个队列头部的元素。如果队列是空的 , 第一个方法抛出NoSuchElementException , 
而第二个方法返回 null。
•E elementC )
•E peek ( )
如果队列不空, 返回这个队列头部的元素 , 但不删除 。 如果队列空 , 第一个方法将拋
出一个 NoSuchElementException , 而第二个方法返回 null。

java . util . Deque < E > 6

•void addFirst ( E element )
•void addLast ( E element )
•boolean offerFirst ( E element )
•boolean offerLast ( E element )
将给定的对象添加到双端队列的头部或尾部。
 如果队列满了 , 前面两个方法将抛出一个IllegalStateException, 而后面两个方法返回false。
•E removeFirst ( )
•E removeLast ( )
•E pollFirstO
•E pollLastO
如果队列不空, 删除并返回队列头部的元素 。 
如果队列为空 , 前面两个方法将拋出一个 NoSuchElementException , 而后面两个方法返回 null 。
•E getFirstO
•E getLastO
•E peekFirstO
•E peekLast ( )
如果队列非空, 返回队列头部的元素 , 但不删除 。 如果队列空 , 前面两个方法将拋出
一个 NoSuchElementException , 而后面两个方法返回 null 。

java . util . ArrayDeque < E > 6

•ArrayDeque ( )
•ArrayDeque ( int initialCapacity )
用初始容量 16 或给定的初始容量构造一个无限双端队列。

18、优先队列:
与 TreeSet一样, 一个优先级队列既可以保存实现了 Comparable 接口的类对象 , 也可以
保存在构造器中提供的 Comparator 对象。
java . util . PriorityQueue 5.0

•PriorityQueue ( )
•PriorityQueue ( int initialCapacity )
构造一个用于存放 Comparable 对象的优先级队列。
•PriorityQueue ( int initialCapacity , Comparator ? super E > c )
构造一个优先级队列 , 并用指定的比较器对元素进行排序。

18、映射:
Java 类库为映射提供了两个通用的实现 : HashMap 和 TreeMap。 这两个类都实现了 Map 接口 。散列映射对键进行散列 , 树映射用键的整体顺序对元素进行排序 , 并将其组织成搜索树。 散列或比较函数只能作用于键 。 与键关联的值不能进行散列或比较 。应该选择散列映射还是树映射呢 ? 与集一样 , 散列稍微快一些 , 如果不需要按照排列顺序访问键, 就最好选择散列 。

19、要想检索一个对象, 必须使用 ( 因而 , 必须记住 ) 一个键 。
String id = " 987 - 98 - 9996 " ;
e = staff , get ( id ) ; / / gets harry
如果在映射中没有与给定键对应的信息 , get 将返回 null。
null 返回值可能并不方便 。 有时可以有一个好的默认值 , 用作为映射中不存在的键 。 然后使用 getOrDefault 方法。
Map < String , Integer > scores = . .
int score = scores . get ( id , 0 ) ; / / Gets 0 if the id is not present

20、基本映射相关API:
java . util . Map < K, V > 1.2//map接口

•V get ( Object key )
获取与键对应的值 ; 返回与键对应的对象 , 如果在映射中没有这个对象则返回 null。键可以为 null。
•default V getOrDefault ( Object key , V defaultValue )
获得与键关联的值 ; 返回与键关联的对象, 或者如果未在映射中找到这个键 , 则返回default Value。
•V put ( K key , V value )
将键与对应的值关系插入到映射中。 如果这个键已经存在 , 新的对象将取代与这个键对应的旧对象。 
这个方法将返回键对应的旧值 。 如果这个键以前没有出现过则返回null 。
键可以为 null , 但值不能为 null 。
•void putAll ( Map < ? extends K , ? extends V > entries )
将给定映射中的所有条目添加到这个映射中。
•boolean containsKey ( Object key )
如果在映射中已经有这个键, 返回true。
•boolean containsValue ( Object value )
如果映射中已经有这个值, 返回true。
• default void forEach ( BiConsumer < ? super K , ? super V > action ) 8
对这个映射中的所有键 / 值对应用这个动作。

java . utii . HashMap<K, V> 1.2

•HashMap ( )
•HashMap ( int initialCapacity )
•HashMap ( int initialCapacity , float 1 oadFactor )

用给定的容量和装填因子构造一个空散列映射 ( 装填因子是一个 0.0 〜 1.0 之间的数值。 这个数值决定散列表填充的百分比 。 一旦到了这个比例 , 就要将其再散列到更大的表中 )。 默认的装填因子是0.75。

java . util . TreeMap < K , V > 1.2

•TreeMap ( )
为实现 Comparable 接口的键构造一个空的树映射。
• TreeMap ( Comparator < ? super K > c )
构造一个树映射 , 并使用一个指定的比较器对键进行排序。
• TreeMap ( Map < ? extends K , ? extends V > entries )
构造一个树映射 , 并将某个映射中的所有条目添加到树映射中。
• TreeMap ( SortedMap < ? extends K , ? extends V > entries )
构造一个树映射 , 将某个有序映射中的所有条目添加到树映射中, 并使用与给定的有序映射相同的比较器。

java . util . SortedMap < K , V > 1.2

• Comparator <? super K > comparator ( )
返回对键进行排序的比较器。 如果键是用 Comparable 接口的 compareTo 方法进行比较的, 返回null 。
•K firstKey( )
• K lastKey ( )
返回映射中最小元素和最大元素。

21、更新映射项:
处理映射时的一个难点就是更新映射项。 正常情况下 , 可以得到与一个键关联的原值 ,完成更新, 再放回更新后的值 。 不过 , 必须考虑一个特殊情况 ,即键第一次出现。 下面来看
一个例子, 使用一个映射统计一个单词在文件中出现的频度 。 看到一个单词 ( word )时, 我
们将计数器增 1, 如下所示 :
counts . put ( word , counts . get ( word ) + 1 ) ;
这是可以的, 不过有一种情况除外 : 就是第一次看到word 时。 在这种情况下 , get会返回 null , 因此会出现一个 NullPointerException 异常。
作为一个简单的补救 , 可以使用 getOrDefault 方法 :
counts , put ( word , counts . getOrDefault ( word , 0 ) + 1 ) ;
另一种方法是首先调用 putlfAbsent 方法。 只有当键原先存在时才会放入一个值 。
counts . putlf Absent ( word , 0 ) ;
counts . put ( word , counts . get ( word ) + 1 ) ; // Now we know that get will succeed
不过还可以做得更好。 merge 方法可以简化这个常见的操作 。 如果键原先不存在 , 下面的调用 :
counts . merge ( word , 1 , Integer : : sum ) ;
将把 word 与 1 关联 , 否则使用 Integer :: sum 函数组合原值和 1 ( 也就是将原值与 1 求和 )

22、P376 与更新映射相关的API不怎么太常用,以后遇到的是时候再总结。

23、映射视图:
初学的时候对java里的映射视图的概念很不理解,因为c++STL中集合本身就是容器的一种,可以直接访问查看元素。但是在java里,集合框架不认为映射本身是一个集合。( 其他数据结构框架认为映射是一个键 / 值对集合,或者是由键索引的值集合。) 不过 , 可以得到映射的视图 ( View ) — 这是实现了Collection 接口或某个子接口的对象 。
在java中映射有 3 种视图 : 键集 、 值集合 ( 不是一个集 ) 以及键 / 值对集 。 键和键 / 值对可以构成一个集 , 因为映射中一个键只能有一个副本 。 下面的方法 :
Set < K > keySet ()
Collection < V > values 0
Set < Map . Entry < K , V » entrySetO
会分别返回这 3 个视图。( 条目集的元素是实现 Map . Entry 接口的类的对象 。 )需要说明的是 , keySet 不是 HashSet 或 TreeSet , 而是实现了 Set 接口的另外某个类的对象。 Set接口扩展了 Collection 接口。 因此 ,可以像使用集合一样使用 keySet。
需要说明的是 , keySet 不是 HashSet 或 TreeSet , 而是实现了 Set 接口的另外某个类的对象。 Set接口扩展了 Collection 接口。 因此 ,可以像使用集合一样使用 keySet。
例如 , 可以枚举一个映射的所有键 :

Set < String > keys = map . keySet();
for ( String key : keys )
{
	 do something with key
}

如果想同时查看键和值, 可以通过枚举条目来避免查找值 。 使用以下代码 :

for ( Map . Entry < String , Employee 〉 entry : staff . entrySetO )
{
	String k = entry . getKeyO ;
 	Employee v = entry . getValueO ;
	do something with k , v
}

提示 : 以上这是原先访问所有映射条目的最高效的方法。 如今 , 只需要使用
forEach 方法 :

counts . forEach ( ( k , v ) - > {
	do something with k , v
} ) ;

24、映射视图相关API:
java.util.Map<K, V> 1.2

•Set < Map . Entry < K , V > > entrySet ( )
返回 Map . Entry 对象 ( 映射中的键 / 值对 ) 的一个集视图。 
可以从这个集中删除元素 ,它们将从映射中删除, 但是不能增加任何元素 。
• Set < K > keySet ( )
返回映射中所有键的一个集视图 。 
可以从这个集中删除元素 , 键和相关联的值将从映射中删除 , 但是不能增加任何元素 。
• Col 1 ection < V >values ()
返回映射中所有值的一个集合视图。 
可以从这个集合中删除元素 ,所删除的值及相应的键将从映射中删除 , 不过不能增加任何元素。

java . util . Map . Entry < K , V > 1.2

• K getKey ()
•V getValueC )
返回这一条目的键或值。
•V setValue ( V newValue )
将相关映射中的值改为新值, 并返回原来的值 。

25、弱散列映射,链接散列映集与映射,枚举集与映射,表示散列映射之后找时间再深入研究。

26、重中之重,关于java视图技术的理解:
用如此多的接口和抽象类来实现数量并不多的具体集合类似乎没有太大必要。 然而 , 这两张图并没有展示出全部的情况 。 通过使用视图( views ) 可以获得其他的实现了 Collection 接口和 Map 接口的对象。 映射类的 keySet 方法就是一个这样的示例。 初看起来 , 好像这个方法创建了一个新集 , 并将映射中的所有键都填进去, 然后返回这个集 。 但是 ,情况并非如此。 取而代之的是 : keySet 方法返回一个实现Set接口的类对象 , 这个类的方法对原映射进行操作。 这种集合称为视图 。

27、具体视图内容,以后找时间深入研究。

28、排序算法API:
java . util . CoIiections 1.2

• static < T extends Comparable < ? super T » void sort ( List < T > elements )
使用稳定的排序算法 , 对列表中的元素进行排序。 这个算法的时间复杂度是 0 ( n log
n ) , 其中 n 为列表的长度。
• static void shuff 1 e ( List < ? > elements )
• static void shuff 1 e ( List < ? > elements , Random r )
随机地打乱列表中的元素。 这个算法的时间复杂度是 0 ( n a(n) ) ,
n 是列表的长度 , a ( n )是访问元素的平均时间。

java . util . List 1.2

• default void sort ( Comparator < ? super T > comparator ) 8
使用给定比较器对列表排序。

java . utii . Comparator < T > 1.2

• static < T extends Comparable < ? super T> > Comparator < T > reverseOrder ( ) 8
生成一个比较器, 将逆置Comparable 接口提供的顺序 。
• default Comparator < T > reversed ( ) 8
生成一个比较器 , 将逆置这个比较器提供的顺序。

29、二分查找算法:
要想查找某个元素 , 必须提供集合 ( 这个集合要实现 List 接口 , 下面还要更加详细地介绍这个问题 ) 以及要查找的元素 。 如果集合没有采用 Comparable 接口的compareTo 方法进行排序 , 就还要提供一个比较器对象 。

i = Collections . binarySearch ( c , element ) ;
i = Collections . binarySearch ( c , element , comparator ) ;

如果 binarySearch 方法返回的数值大于等于 0 , 则表示匹配对象的索引 。 也就是说 ,c . get ( i ) 等于在这个比较顺序下的 element 。 如果返回负值 , 则表示没有匹配的兀素 。 但是 ,可以利用返回值计算应该将 element 插人到集合的哪个位置 , 以保持集合的有序性 。 插人的
位置是insertionPoint = - i - 1 ;这并不是简单的 - i, 因为 0 值是不确定的 。 也就是说 , 下面这个操作 :

if ( i < 0 )
c . add ( - i - 1 , element ) ;

将把元素插人到正确的位置上。

30、二分查找只能对支持随机访问的数组有用:
只有采用随机访问, 二分査找才有意义 。 如果必须利用迭代方式一次次地遍历链表的一半元素来找到中间位置的元素, 二分査找就完全失去了优势 。 因此 , 如果为 binarySearch 算法提供一个链表 , 它将自动地变为线性查找。

31、 Collections 类常用算法API合集:

java . util . Collections 1.2
•static < T extends Comparable < ? super T > > T min ( Collection < T > elements )
•static < T extends Comparable < ? super T > > T max ( Col 1 ection < T > elements )
•static < T > min ( Col 1 ection < T > elements , Comparator ? super T > c )
•static < T > max ( Col 1 ection < T > elements , Comparator ? super T > c )
返回集合中最小的或最大的元素 ( 为清楚起见, 参数的边界被简化了 ) 。
•static < T > void copy ( List < ? super T > to , List < T > from )
将原列表中的所有元素复制到目辱列表的相应位 1上。 目标列表的长度至少与原列表一样 。
•static < T > void fill ( List < ? super T > l , T value )
将列表中所有位置设置为相同的值。
•static < T > boolean addAll ( Collection < ? super T > c , T . . . values ) 5.0
将所有的值添加到集合中。 如果集合改变了 , 则返回true。
•static < T > boolean replaceAll ( List < T > l , T oldValue , T newValue ) 1.4
用 newValue 取代所有值为 oldValue 的元素 。
•static int indexOfSubList ( List < ? > l , List < ? > s ) 1.4
•static int 1 astlndexOfSubList ( List < ? > l , List < ? > s ) 1.4
返回 1 中第一个或最后一个等于 S 子列表的索引 。 如果 1 中不存在等于 S 的子列表 , 则
返回 - 1。 例如 , 1 为 [ s , t , a , r ], s 为 [ t , a , r ] , 两个方法都将返回索引 1。
•static void swap ( List < ? > l , int i , int j ) 1.4
交换给定偏移量的两个元素。
• static void reverse ( List < ? > l )
逆置列表中元素的顺序。 例如 , 逆置列表 [ t , a , r ]后将得到列表 [ r , a , t ]。 这个方法的时
间复杂度为 O ( n ), n为列表的长度。
•static void rotate ( List < ? > l , int d ) 1.4
旋转列表中的元素 , 将索引 i 的条目移动到位置 ( i + d ) % l . size ( ) 0 例如 , 将列表 [ t, a ,
r ] 旋转移 2 个位置后得到 [ a , r, t ] 。 这个方法的时间复杂度为 O ( n ) ,n 为列表的长度。
•static int frequency ( Collection < ? > c , Object o ) 5.0
返回 c 中与对象 o 相同的元素个数。
•boolean disjoint ( Collection < ? > cl , Collection < ? > c 2 ) 5.0
如果两个集合没有共同的元素 , 则返回 true。

32、重点:传统数组与集合之间的转换
如果需要把一个数组转换为集合, Arrays . asList 包装器可以达到这个目的 。 例如 :

String [ ] values = . .
HashSet < String > staff = new HashSet<> ( Arrays . asList ( values )) ;

从集合得到数组会更困难一些。 当然 , 可以使用 toArray 方法 :

Object [ ] values = staff . toArray() ;

不过, 这样做的结果是一个对象数组 。 尽管你知道集合中包含一个特定类型的对象 , 但不能使用强制类型转换 :

String[ ] values = ( String[ ]) staff . toArray 0 ; / / Error !

toArray 方法返回的数组是一个 Object [ ] 数组 , 不能改变它的类型。 实际上 , 必须使用
toArray 方法的一个变体形式, 提供一个所需类型而且长度为 0 的数组 。 这样一来 , 返回的数组就会创建为相同的数组类型 :

String [ ] values = staff . toArray ( new StringtO ] ) ;

如果愿意, 可以构造一个指定大小的数组 :

staff . toArray ( new String [ staff . size ( ) ] ) ;

在这种情况下, 不会创建新数组 。
注释 : 你可能奇怪为什么不能直接将一个 Class 对象 ( 如 String . class ) 传递到 to Array 方法。 原因是这个方法有 “双重职责 ” , 不仅要填充一个已有的数组 ( 如果它足够长 ), 还要创建一个新数组。

33、栈:

 java . util . Stack < E > 1.0
•E push ( E item )
将 item 压人桟并返回 item。
•E pop ()
弹出并返回栈顶的 item。 如果栈为空 , 请不要调用这个方法 。
•E peek ()
返回栈顶元素, 但不弹出 。 如果栈为空 , 请不要调用这个方法 。

34、9.6遗留的集合其他部分以后找时间深入研究。

猜你喜欢

转载自blog.csdn.net/NCUscienceZ/article/details/83474689