List类知识点总结

List类知识点总结

LinkedList

链表集合,继承AbstractSequentialList,实现DequeCloneableSerializable

  1. 实现Deque,可以当作双端序列使用
  2. Cloneable:可被克隆
  3. Serializable:可被序列化

属性

1
2
3
4
5
6
7
8
transient int size = 0; // 长度
transient Node<E> first; // 头节点
transient Node<E> last; // 尾节点
private static class Node<E> {
E item; // 元素
Node<E> next; // 下一节点
Node<E> prev; // 上一节点
}

可见LinkedList实现的是双向链表

构造

1
2
3
4
5
6
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

方法

方法大全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Queue接口的方法
boolean add(E e) // 尾部添加一个节点
E element() // 获取头节点元素
boolean offer(E e) // 尾部添加元素
E peek() // 获取头节点元素
E poll() // 获取头节点元素并移除
E remove() // 获取头节点元素并移除

// Deque接口的方法
void addFirst(E e) // 添加元素至头节点
void addLast(E e) // 添加元素至尾节点
ListIterator<E> listIterator(int index) // 迭代器
Iterator<E> descendingIterator() // 逆序迭代器
E getFirst() // 获取头节点元素
E getLast() // 获取尾节点元素
boolean offerFirst(E e) // 头部添加元素
boolean offerLast(E e) // 尾部添加元素
E peekFirst() // 获取头节点元素,空集合返回null
E peekLast() // 获取尾节点元素,空集合返回null
E pollFirst() // 获取头节点元素并移除,空集合返回null
E pollLast() // 获取尾节点元素并移除,空集合返回null
E pop() // 出栈,弹出链表头节点
void push(E e) // 压栈,添加在链表头部(与add()相反)
boolean remove(Object o) // 移除指定节点元素
E removeFirst() // 获取头节点元素并移除
E removeLast() // 获取尾节点元素并移除
boolean removeFirstOccurrence(Object o) // 移除指定元素(出现的第一个)
boolean removeLastOccurrence(Object o) // 移除指定元素(出现的最后一个)

// 其它
void add(int index, E element) // 指定位置添加一个节点
boolean addAll(Collection<? extends E> c) // 尾部添加指定集合中所有元素
boolean addAll(int index, Collection<? extends E> c) // 指定位置添加指定集合中所有元素
E get(int index) // 获取指定位置节点元素
E set(int index, E element) // 替换指定位置元素
E remove(int index) // 获取指定位置节点元素并移除
int indexOf(Object o) // 获取元素首次出现的位置
int lastIndexOf(Object o) // 逆序获取元素首次出现的位置
void clear() // 清除所有元素
boolean contains(Object o) // 是否包含某元素
int size() // 大小
Spliterator<E> spliterator() // spliterator
Object[] toArray() // 将集合以数组形式返回
<T> T[] toArray(T[] a) // 将集合以数组形式返回,类型、大小由参数决定,不足返回null
Object clone() // 浅复制集合

add

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last; // 保存last
final Node<E> newNode = new Node<>(l, e, null); // Node(pre, element, next),创建新节点,next为null
last = newNode; // last为新节点
if (l == null)
first = newNode; // 链表为空时,初始化first
else
l.next = newNode; // 链表不为空时,上一节点的next指向newNode
size++;
modCount++;
}
public void add(int index, E element) {
checkPositionIndex(index); // 检查index >= 0 && index <= size
if (index == size) // 尾部添加节点
linkLast(element);
else
linkBefore(element, node(index));
}
void linkBefore(E e, Node<E> succ) {
final Node<E> pred = succ.prev; // 保存原位置节点前一个节点
final Node<E> newNode = new Node<>(pred, e, succ); // 创建新节点,设置pre,next
succ.prev = newNode; // 设置原位置节点的pre为新节点
if (pred == null)
first = newNode; // 原位置节点前一个节点为null,设置新节点为头节点
else
pred.next = newNode; // 原位置节点的前一个节点的next为新节点
size++;
modCount++;
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c); // 转为addAll(index, c)
}
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index); // 检查index >= 0 && index <= size
Object[] a = c.toArray(); // 转为数组
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null; // 插入到尾部
pred = last;
} else {
succ = node(index); // 插入到位置i(0<=i<size)
pred = succ.prev;
}
for (Object o : a) { // 遍历节点,进行插入操作
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null); // 设置pre,next
if (pred == null)
first = newNode; // pred为null,重置first
else
pred.next = newNode; // 设置前一个节点的next
pred = newNode; // 重置pred
}
if (succ == null) {
last = pred; // 插入到尾部,重置last
} else {
pred.next = succ; // 设置插入的最后一个节点的next
succ.prev = pred; // 设置原位置节点的prev
}
size += numNew;
modCount++;
return true;
}

迭代方式

  1. 随机访问:list.get(i),效率超级低
  2. 迭代器:list.iterator(),效率最高
  3. foreach:for(Object i: list),效率其次

ArrayList

动态数组,继承AbstractList,实现List、RandomAccess、Cloneable、Serializable。

  • Q:ArrayList继承了AbstractList,为什么还要实现List?
  • A:显式表明ArrayList实现了ListAbstractList只是为了提升List实现的代码重用。
  1. RandomAccess:标记接口,表明List的某个实现支持随机访问。
  2. Cloneable:可被克隆``
  3. Serializable:可被序列化

不是线程安全,多线程可以选择VectorCopyOnWriteArrayList

属性

1
2
3
4
// 保存数据的数组
transient Object[] elementData;
// ArrayList中实际数据的数量
private int size;
  • Q:elementData需要序列化,为什么还要被transient修饰,被transient修饰了,为什么还能被序列化?
  • AelementData是一个缓存数组,通常会预留容量,所以elementData中只有实际存放的元素需要被序列化,故被transient修饰防止所有元素被序列化;ArrayList中元素还能被序列化是因为它重写了writeObject()方法(debug看到这个方法是被反射获取调用的)。
1
2
3
4
5
6
7
8
9
10
11
12
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
int expectedModCount = modCount;
s.defaultWriteObject();
s.writeInt(size);
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]); // 只序列化size个元素
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}

构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 不可变的空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 初始化指定大小的数组
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
/**
*构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回
*如果指定的集合为null,throws NullPointerException。
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
  • 第一个构造函数会将elementData初始化为空数组
  • 第二个构造函数会将elementData初始化为指定大小的数组

细心的同学一定会发现 :以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10。

方法

方法大全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
boolean add(E e) // 尾部添加元素
void add(int index, E element) // 在指定位置添加元素
boolean addAll(Collection<? extends E> c) // 尾部添加集合中所有元素
boolean addAll(int index, Collection<? extends E> c) // 指定位置添加集合中所有元素

void clear() // 清除所有元素
Object clone() // 浅复制集合
boolean contains(Object o) // 是否包含某元素
void ensureCapacity(int minCapacity) // 确保ArrayList的容器能装下minCapacity个元素

void forEach(Consumer<? super E> action) // 对每个元素执行action操作(迭代器模式)
E get(int index) // 获取指定位置元素
int indexOf(Object o) // 获取指定元素位置
boolean isEmpty() // 是否为空集合

Iterator<E> iterator() // 获取迭代器
int lastIndexOf(Object o) // 获取指定位置,倒序查找

ListIterator<E> listIterator() // 返回迭代器ListIterator
ListIterator<E> listIterator(int index) // 在指定位置返回迭代器ListIterator

E remove(int index) // 移除并获取指定位置元素
boolean remove(Object o) // 移除元素,仅移除遍历到的第一个
boolean removeAll(Collection<?> c) // 移除指定集合中所有元素
boolean removeIf(Predicate<? super E> filter) // 移除满足条件的元素
void replaceAll(UnaryOperator<E> operator) // 按照operator操作替换所有元素
boolean retainAll(Collection<?> c) // 只保留包含在指定集合中的元素
E set(int index, E element) // 设置指定位置的元素值
int size() // 集合大小
void sort(Comparator<? super E> c) // 根据指定比较方式comparator排序
Spliterator<E> spliterator() // 获取集合的spliterator,不会用
List<E> subList(int fromIndex, int toIndex) // 获取fromIndex-toIndex的子集合
Object[] toArray() // 转化为数组
<T> T[] toArray(T[] a) // 创建一个新数组传入,返回新数组类型元素,元素不够置null
void trimToSize() // 缩减ArrayList容器的大小至真实存放元素的数量

add/扩容机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保容器能装下(size+1)个元素
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheckForAdd(index); // 数组越界检查
ensureCapacityInternal(size + 1);
// arraycopy(src, srcPos, dest, destPos, length) 将src[srcPos, srcPos+length]复制到dest[destPos, destPos+length]
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
// 数组越界检查
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); // 越界抛出异常
}

当添加元素时,会调用如下方法,若elementData为空数组,则将它扩展为默认长度(10)的数组;若添加元素后elementData长度不够,将会将elementData扩展为原来的1.5倍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 默认容器大小
private static final int DEFAULT_CAPACITY = 10;
private void ensureCapacityInternal(int minCapacity) {
//当要add 进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
// 确保ArrayList能装下minCapacity个元素
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

/**
* ArrayList扩容的核心方法。
*/
private void grow(int minCapacity) {
// oldCapacity为旧容量,newCapacity为新容量
int oldCapacity = elementData.length;
//将oldCapacity 右移一位,其效果相当于oldCapacity /2,
//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
int newCapacity = oldCapacity + (oldCapacity >> 1);
//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,
//如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

具体逻辑

如果通过元素值添加,确保容器能装下;如果通过索引添加,之前还需要数组越界检查

  • 当我们要 add 进第1个元素到 ArrayList 时,elementData.length 为0 (因为还是一个空的 list),因为执行了 ensureCapacityInternal() 方法 ,所以 minCapacity 此时为10。此时,minCapacity - elementData.length > 0成立,所以会进入 grow(minCapacity) 方法。
  • 当add第2个元素时,minCapacity 为2,此时e lementData.length(容量)在添加第一个元素后扩容成 10 了。此时,minCapacity - elementData.length > 0不成立,所以不会进入 (执行)grow(minCapacity) 方法。
  • 添加第3、4···到第10个元素时,依然不会执行grow方法,数组容量都为10。
  • 直到添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进入grow方法进行扩容。

同时注意一下如果需要容量大于MAX_ARRAY_SIZE会进入hugeCapacity()方法:

1
2
3
4
5
6
7
8
9
10
11
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//对minCapacity和MAX_ARRAY_SIZE进行比较
//若minCapacity大,将Integer.MAX_VALUE作为新数组的大小
//若MAX_ARRAY_SIZE大,将MAX_ARRAY_SIZE作为新数组的大小
//MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

remove

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public E remove(int index) {
rangeCheck(index); // 越界检查
modCount++;
E oldValue = elementData(index); // 取出旧值,待返回
int numMoved = size - index - 1; // 待移动的个数
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); // 向前移动一个位置
elementData[--size] = null; // 最后一个元素置null
return oldValue;
}
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index); // 所有元素向前移动一个位置
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c); // 需要非空值,null报空指针异常
return batchRemove(c, false);
}
// 批量删除
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement) // complement=false
elementData[w++] = elementData[r]; // 只保留c中不存在的元素
} finally {
if (r != size) { // 不解,为什么r可能!=size
System.arraycopy(elementData, r, elementData, w, size - r);
w += size - r;
}
if (w != size) {
for (int i = w; i < size; i++) // 剩余元素全置null
elementData[i] = null;
modCount += size - w;
size = w; // 重置size
modified = true; // 修改flag
}
}
return modified;
}

set

1
2
3
4
5
6
public E set(int index, E element) {
rangeCheck(index); // 越界检查
E oldValue = elementData(index);
elementData[index] = element; // 设置新值
return oldValue; // 返回旧值
}

get

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public E get(int index) {
rangeCheck(index);
return elementData(index); // elementData(int index)方法,等同于elementData[index]
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null) // 返回遍历到的第一个元素位置
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1; // 不存在返回-1
}
public boolean contains(Object o) {
return indexOf(o) >= 0; // 使用indexOf()方法检测是否包含
}
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e)) // 一旦不包含某元素,返回false
return false;
return true;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}

System.arraycopy()和Arraya.copyOf()

联系:

看两者源代码可以发现 copyOf() 内部实际调用了 System.arraycopy() 方法

区别:

arraycopy() 需要目标数组,将原数组拷贝到你自己定义的数组里或者原数组,而且可以选择拷贝的起点和长度以及放入新数组中的位置 copyOf() 是系统自动在内部新建一个数组,并返回该数组。

ensureCapacity

ArrayList 源码中有一个 ensureCapacity 方法不知道大家注意到没有,这个方法 ArrayList 内部没有被调用过,所以很显然是提供给用户调用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
如有必要,增加此 ArrayList 实例的容量,以确保它至少可以容纳由minimum capacity参数指定的元素数。
*
* @param minCapacity 所需的最小容量
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;

if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}

最好在 add 大量元素之前用 ensureCapacity 方法,以减少增量重新分配的次数

迭代方式

  1. 随机访问:list.get(i),效率最高
  2. 迭代器:list.iterator()
  3. foreach:for(Object i: list)

Collections工具类

Collections 工具类常用方法:

  1. 排序
  2. 查找,替换操作
  3. 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合)

排序操作

1
2
3
4
5
6
void reverse(List list)//反转
void shuffle(List list)//随机排序
void sort(List list)//按自然排序的升序排序
void sort(List list, Comparator c)//定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j)//交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面。

查找替换操作

1
2
3
4
5
6
7
int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)//根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c)//根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素。
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替换旧元素

同步控制

Collections提供了多个synchronizedXxx()方法·,该方法可以将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。

我们知道 HashSet,TreeSet,ArrayList,LinkedList,HashMap,TreeMap 都是线程不安全的。Collections提供了多个静态方法可以把他们包装成线程同步的集合。

Collections还可以设置不可变集合,提供了如下三类方法:

1
2
3
4
emptyXxx(): 返回一个空的、不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。
singletonXxx(): 返回一个只包含指定对象(只有一个或一个元素)的不可变的集合对象,此处的集合可以是:List,Set,Map。
unmodifiableXxx(): 返回指定集合对象的不可变视图,此处的集合可以是:List,Set,Map。
上面三类方法的参数是原有的集合对象,返回值是该集合的”只读“版本。

Arrays

常见操作

  1. 排序 : sort()
  2. 查找 : binarySearch()
  3. 比较: equals()
  4. 填充 : fill()
  5. 转列表: asList()
  6. 转字符串 : toString()
  7. 复制: copyOf()

方法

sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// *************排序 sort****************
int a[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
// sort(int[] a)方法按照数字顺序排列指定的数组。
Arrays.sort(a);
System.out.println("Arrays.sort(a):");
for (int i : a) {
System.out.print(i);
}
// 换行
System.out.println();

// sort(int[] a,int fromIndex,int toIndex)按升序排列数组的指定范围
int b[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
Arrays.sort(b, 2, 6);
System.out.println("Arrays.sort(b, 2, 6):");
for (int i : b) {
System.out.print(i);
}
// 换行
System.out.println();

int c[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
// parallelSort(int[] a) 按照数字顺序排列指定的数组(并行的)。同sort方法一样也有按范围的排序
Arrays.parallelSort(c);
System.out.println("Arrays.parallelSort(c):");
for (int i : c) {
System.out.print(i);
}
// 换行
System.out.println();

// parallelSort给字符数组排序,sort也可以
char d[] = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
Arrays.parallelSort(d);
System.out.println("Arrays.parallelSort(d):");
for (char d2 : d) {
System.out.print(d2);
}
// 换行
System.out.println();

binarySearch()

1
2
3
4
5
6
7
8
// *************查找 binarySearch()****************
char[] e = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
// 排序后再进行二分查找,否则找不到
Arrays.sort(e);
System.out.println("Arrays.sort(e)" + Arrays.toString(e));
System.out.println("Arrays.binarySearch(e, 'c'):");
int s = Arrays.binarySearch(e, 'c');
System.out.println("字符c在数组的位置:" + s);
分享到: