参加了数次竞赛之后,我发现我的瓶颈所在——语法。于是今天来复习一下常用的Java库函数吧。
比赛中用java8还是10我就不care啦,我直看官方最新文档。地址在 https://docs.oracle.com/javase/10/docs/api/java/util/package-summary.html
首先看到java.util是一个package,而java.base是一个module。我简单查了一下,据说module是在java9时候出现的程序结构术语,我没有查到名词解释,从文档里看module比package要高一个抽象级别。概念这种东西,真的有时候解释不清楚还不如不解释,大家意会为主吧
官方文档里关于Java.util的解释是:“Contains the collections framework, some internationalization support classes, a service loader, properties, random number generation, string parsing and scanning classes, base64 encoding and decoding, a bit array, and several miscellaneous utility classes. This package also contains legacy collection classes and legacy date and time classes”。从文字上看,包含的内容很杂,很多,但是其实最主要的肯定排在最前面咯,考过雅思和GRE的同学们都懂,阅读理解最重要的就是不需要全部读懂,读懂最重要的就行。我们画重点的就是——collections framework!
collections framework是有tutorial的,在这里https://docs.oracle.com/javase/tutorial/collections/index.html
原来我一直以为官方文档没有例子很不友好,是我误会了,还是有教程可以follow的哈。
跟着官方教程,先从interfaces走起。
借用一下官方的图,看一下核心的collection interfaces有哪些。我们发现map和collection是分开放置了,但是我们发现图的题目没有把map排除在collection外面,所以往下读,有提示:“Note also that the hierarchy consists of two distinct trees — a Map is not a true Collection.” 分开单独一棵树就是为了告诉大家Map不是真正意义上的Collection。那为什么不放在别的地方?(这个问题是留给我们自己的)
关于这个类,官方的介绍很简单明了:“The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered. The JDK does not provide any direct implementations of this interface: it provides implementations of more specific subinterfaces like Set and List. This interface is typically used to pass collections around and manipulate them where maximum generality is desired”。
如图所示,collection这颗树的根节点,就是collection。collection用于表示一组对象——也就是他的元素。有些collection允许重复元素,有些不允许。JDK不提供这个接口(Collection)的任何直接的Implementation。这个接口通常是为了传递collections并在希望具有最大通用性的情况下操纵他们。
官方教程在这里:https://docs.oracle.com/javase/tutorial/collections/interfaces/set.html
教程里比较有用的一句话就是:“The Set interface contains only methods inherited from Collection and adds the restriction that duplicate elements are prohibited.” Set这个类只有继承自Collection的方法而已哦,外加一个禁止重复元素的限制。 这是一个多么听话的孩子啊,除了妈妈告诉的方法就没有别的方法了!
比较常用的instance Method,我记下来,以便查询
方法名 | 用途 | 返回值类型 |
---|---|---|
size( ) | 返回集合的元素个数 | int |
equals( ) | 将集合与特定元素比较,看是否相同 | boolean |
isEmpty() | 判断集合是否为空 | boolean |
contains(Object o) | 判断集合是否包含元素o | boolean |
iterator() | 返回集合元素的Iterator | Iterator |
toArray() | 返回集合元素的数组形式 | Object[] |
toArray(T[] a) | 返回集合元素的T类型数组 (我理解是输出为我们指定的类型T) | T[] |
add(E e) | 如果集合里没有e元素,就添加到集合。如果集合里没有e元素,就返回true | boolean |
remove(Object o) | 如果集合里存在o元素,就删除它。如果集合里存在o元素,就返回true | boolean |
containsAll(Collection c) | 判断集合里是否包含给定集合的所有元素 | boolean |
addAll(Collection c) | 如果给定集合的元素和集合现存元素有差异,添加差异元素。如有差异,返回true.(相当于并集操作) | boolean |
retainAll(Collection c) | 保留与给定集合元素重合的元素,相当于交集操作。如集合有变化,返回true | boolean |
clear() | 清空集合所有元素 | void |
hashCode() | 返回集合的hashcode,默认是所有元素hashcode之和。空集的hashcode是0 | int |
另有一个default method,我还没有理解,后面实验一下:
方法名 | 用途 | 返回值 |
---|---|---|
spliterator() | 生成一个集合元素的spliterator | Spliterator |
Java平台提供三个Set的implementation—— HashSet, TreeSet, and LinkedHashSet。 从官方的介绍来看,HashSe利用Hash table来实现元素存储,的性能最好,但是元素顺序没有保障;TreeSet用红黑树来实现元素存储,顺序按照字母顺序,比HashSet慢一些;LinkedHashSet用到hash table和linkedlist,元素按照插入顺序排列,性能只比HashSet差一点点。
SortedSet我们就不细究了吧,看名字就明白特殊之处了。
根据官方教程:List 是一个有序的 Collection (有时也叫equence). Lists 允许元素重复. 除了继承自Collection的方法, List interface 还包含特别的访问、搜索、轮询、范围视图等。这样难怪,因为List还有一个妈妈,叫 Iterator。所以它比Set的背景更大。
Java平台提供两个implementation, 一个是ArrayList,性能比较好;另一个是 LinkedList,在某些场景下性能较好。
常用方法列表:
方法名 | 用途 | 返回值类型 |
---|---|---|
add(E e) | 如果集合里没有e元素,就添加到集合。如果集合里没有e元素,就返回true | boolean |
add(int index, E e) | 在index的位置插入元素e | void |
addAll(int index, Collection c) | 在index的位置插入集c | boolean |
addAll(Collection c) | 在列表末尾添加c中的元素 | boolean |
contains(Object o) | 判断列表是否包含元素o | boolean |
containsAll(Collection c) | 判断列表里是否包含给定集的所有元素 | boolean |
clear() | 情况列表的所有元素 | void |
equals( ) | 将列表与特定对象比较,看是否相同 | boolean |
get(int index) | 返回列表中在 index 位置的元素 | E |
hashCode() | 返回列表的hashcode,默认是所有元素hashcode之和。空集的hashcode是0 | int |
indexOf(Object o) | 返回列表中 o 的位置,如果o没有出现, 返回-1 | int |
isEmpty() | 判断列表是否为空 | boolean |
iterator() | 返回集合元素的Iterator | Iterator |
lastIndexOf(Object o) | 返回列表中 o 最后出现的位置,如果o没有出现, 返回-1 | int |
listIterator() | 返回列表的 listIterator。 ListIterator有很好的特性,可以双向遍历 | ListIterator |
listIterator(int index) | 返回列表的 listIterator, 从index位置开始 | ListIterator |
remove(int index) | 删除列表中index位置的元素 | E |
remove(Object o) | 如果列表里存在o元素,就删除它。如果列表里存在o元素,就返回true | boolean |
removeAll(Collection c) | 去掉列表中存在于c集中的所有元素 | boolean |
replaceAll(UnaryOperator operator) | 将列表中的元素在指定运算符下计算,用计算结果替换原来的元素 | 默认void |
retainAll(Collection c) | 保留与给定集合元素重合的元素,相当于交集操作。如集合有变化,返回true | boolean |
set(int index, E element) | 用 elemen t替换列表中 index 位置的元素 | E |
size( ) | 返回列表的元素个数 | int |
sort(Comparator c) | 按照comparator的规则对列表元素进行排序 | 默认void |
spliterator() | 为列表元素生成一个spliterator | Spliterator |
subList(int fromIndex, int toIndex) | 生成一个从 fromIndex开始到 toIndex结束的子列表 | List |
toArray() | 返回集合元素的数组形式 | Object[] |
toArray(T[] a) | 返回集合元素的T类型数组 (我理解是输出为我们指定的类型T) | T[] |
在官方教程里找到了一个好东东,algorithm!https://docs.oracle.com/javase/tutorial/collections/algorithms/index.html, 这里有好多又快又好的算法捷径,藏得好深啊!
Collections的内置函数:
函数名 | 用途 | 返回值类型 |
---|---|---|
sort( Collection e) | 自然排序 e | void |
shuffle( Collection e ) | 打乱顺序 | void |
reverse( List list) | 将list元素逆序排列 | void |
swap(lList list, int i, int j) | 交换下标 i 和 j的元素的位置 | void |
fill( List list, String str ) | 用str填充list | void |
copy( List list1, List list2) | 将list2的内容复制到list1 | void |
binarySearch(List list, E key) | 返回list中key的位置,如果没有返回 (-(insertion point) - 1) | int |
frequency(List list, E e) | 返回e元素在list中出现的频率 | int |
disjoint( List list1, List list2) | 判断 list1 和 list2 是否没有交集,没有交集返回true | boolean |
min( List list ) | 返回list里最小的元素 | E |
max( List list ) | 返回list中最大的元素 | E |
官方文档里说的很清楚,“A Queue is a collection for holding elements prior to processing”,也就是说队列只是为了在对数据进行处理加工之前存放元素的。所以,队列的方法比起前面的两个就少了很多,基本上就涉及到存取。
方法名 | 用途 | 返回值类型 |
---|---|---|
add(E e) | 如果空间允许,将e元素添加到队列,返回true。如果超出空间限制,抛出异常 | boolean |
element() | 读取队列的头元素 | E |
offer(E e)) | 如果空间允许,将e元素添加到队列,返回true;不抛异常 | boolean |
peek()) | 读取队列的头元素,如果队列为空,返回null | E |
poll() | 读取并删除队列的头元素,如果空队列,返回null | E |
remove() | 读取并删除队列的头元素 | E |
当然Collections的基本方法Queue也都继承了的,还有Iterable的forEach。Queue也是个有双亲的孩子。
Queue的顺序感很强,通常是先进先出(FIFO),也就是队尾入队,队首出队。
官方文档里说道:A linear collection that supports element insertion and removal at both ends. The name deque is short for “double ended queue” and is usually pronounced “deck”。首先,Deque是可以从两端操作元素的Collection,然后我们就知道了它的真名,和昵称。历史无数次的证明,昵称总比真名要流传的广。
Deque的方法比较多了,Queue有的方法我就不列了,显得重复,大家记住Queue有的,他的兄弟Deque都有就行了。下面就列出区别于Queue的方法
方法名 | 用途 | 返回值类型 |
---|---|---|
addFirst(E e) | 如果空间允许,将e元素添加到队首。如果超出空间限制,抛出异常IllegalStateException | void |
addLast(E e) | 如果空间允许,将e元素添加到队尾。如果超出空间限制,抛出异常IllegalStateException | void |
contains(Object o) | 判断列表是否包含元素o | boolean |
descendingIterator() | 返回Deque的逆序Iterator | Iterator |
getFirst() | 读取deque的头元素 | E |
getLast() | 读取deque的尾元素 | E |
offerFirst(E e) | 如果空间允许,将e元素添加到队首。 | boolean |
offerLast(E e) | 如果空间允许,将e元素添加到队尾。 | boolean |
pollFirst() | 读取并删除deque的头元素,如果是空队,返回null | E |
pollLast() | 读取并删除deque的尾元素,如果是空队,返回null | E |
pop() | deque作为栈时的出栈操作 | E |
push(E e) | deque作为栈时的压栈操作,空间不允许时抛出 IllegalStateException | void |
remove(Object o) | 删除 o 在deque里的最早出现的对应值 | boolean |
removeFirst() | 读取并删除deque的头元素 | E |
removeFirstOccurrence(Object o) | 删除 o 在deque里的最早出现的对应值 | boolean |
removeLast() | 读取并删除deque的尾元素 | E |
removeLastOccurrence(Object o) | 删除 o 在deque里的最后出现的对应值 | boolean |
根据官方的解释,Map就是一个键值映射,Map的键自然是不能有重复的,一个Key最多只能映射到一个Value。这个让我回想起自己前几天做的题目,确实我当时想着一个Key 映射到多个值呢,真的是学习不到位啊~~
前面官方文档里也说了,Map不是真正意义上的Collection,这里官方文档就说清楚了,Map只是提供三种Collection views:键,值,键值的映射关系。
Map的order其实比较复杂,TreeMap有明确的排序,但是HashMap就不一样啦。 我也记得老师说过,HashMap的排序不完全时是从大到小的,有一次作业用HashMap给1到100的数字排序,就比较有意思的结果。
键是不可以为空的,但是一些不合法的键赋值操作也不一定就会抛出异常。官方文档里说到的操作其实我都还不熟悉,没有体会,似乎可变的对象作为key会带来很大麻烦。大家有兴趣,自己去了解一下:https://docs.oracle.com/javase/10/docs/api/java/util/Map.html
值得注意的是这一条:“Some map operations which perform recursive traversal of the map may fail with an exception for self-referential instances where the map directly or indirectly contains itself. This includes the clone(), equals(), hashCode() and toString() methods. Implementations may optionally handle the self-referential scenario, however most current implementations do not do so” Map把自己作为一个value是可以的,那么就可以recursive traversal, 但是这里说到可能会异常的情况,看起来不很稳定。留心一下,不知道以后会不会遇到这类题目啊~~
Map的一个static interface是 Map.Entry
Map的方法好多,还有很多static的方法涉及到 Unmodifiable Map, 基于目前的菜鸟属性,我就不去学啦,因为我估计我十有八九也用不到。既然复习吗,我们就记下来常用的insntance method
方法名 | 用途 | 返回值类型 |
---|---|---|
clear() | 删除map的所有映射 | void |
compute(K key, BiFunction remappingFunction) | 利用remappingFunction在给定Key的基础上利用旧Value计算新的Value,如果旧mapping不存在则Value为null | default V |
computeIfAbsent(K key, Function mappingFunction) | 当Map中不包含给定key时,利用mappingFunction生成key的mapping | default V |
computeIfPresent(K key, BiFunction remappingFunction | 在Map中包含给定key的情况下,利用remappingFunction在给定Key的基础上生成新的Value | default V |
containsKey(Object key) | 如果Map包含有key的mapping,就返回true | boolean |
containsValue(Object value) | 如果Map包含有value的mapping,就返回true | boolean |
entrySet() | 返回Map中所有映射的Set视图 | Set |
equals(Object o) | 如果o也是一个Map,而且所有mapping都相等,就返回true。相等的Map的entrySet也相等 | boolean |
forEach(BiConsumer action) | 对所有mapping依次执行action操作,直到轮完所有mapping或者action抛出异常 | default void |
get(Object key) | 返回对应key的value,如果map没有对应的key的mapping,返回null | V |
getOrDefault(Object key, V defaultValue) | 返回对应key的value,如果map没有对应的key的mapping,返回defaultValue | default V |
hashCode() | 返回Map的hashcode | int |
isEmpty() | 如果map不包含任何键值映射,则返回true | boolean |
keySet() | 返回Map的所有key的Set视图 | Set |
merge(K key, V value, BiFunction remappingFunction) | 如果给定的key没有关联到任何value或者关联到null值,则映射到remappingFunction算出的value | default V |
put(K key, V value) | 建立key和value的映射 | V |
putAll(Map m) | 从给定map复制所有映射 | void |
putIfAbsent(K key, V value) | 如果给定的key还没有关联到value,或者映射到null,则将其关联到给定的value,并返回null。否则,返回当前的映射value. | V |
remove(Object key) | 如果key的映射存在,则将其删除 | V |
remove(Object key, Object value) | 当且仅当key和value的映射存在时(返回true)将其删除 | default boolean |
replace(K key, V value) | 当且仅当包含key的映射存在时将其value替换 | default V |
replace(K key, V oldValue, V newValue) | 当且仅当包含key的映射存在时(返回true)将oldValue替换成newValue | default boolean |
replaceAll(BiFunction function) | 使用function替换每一个entry的value,直到所有entry都被替换或者function抛出异常 | void |
size() | 返回map中键值映射的数量 | int |
values() | 返回map中所有value的Collection视图 | Collection |
复习内容大致就这么多。准备多多练习,希望可以在下一次Leetcode的比赛中签到成功。