Collections API继续深度学习:
public static <T> boolean addAll(Collection<? super T> c,T... elements)将elements所有元素添加到集合c中,例如:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Random;
public class Main5 {
public static void main(String[] args) {
// int arr2 [] = { 75, 52, 99, 102, 78, 23 };//数组定义并直接初始化[]左右都可以
int[] arr1 = { 75, 52, 99, 102, 78, 23 };
ArrayList<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i <= 4; i++) {
list.add(random.nextInt());
}
System.out.println(list);
System.out.println(Collections.addAll(list, new Integer[] { 1, 2, 3, 4, 5 }));
System.out.println(list);
}
}
java.util.Collections.addAll(Collection<? super Integer>, Integer...)源码如下,其实也没有什么神奇之处,也就是使用增强for循环,此处建议也建议我们多多使用增强for循环,efficient java 也有同样建议。
public static <T> boolean addAll(Collection<? super T> c, T... elements) {
boolean result = false;
for (T element : elements)
result |= c.add(element);
return result;
}
package com.daxin.collections;
import java.util.Collections;
import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
public class Main6 {
public static void main(String[] args) {
//ConcurrentLinkedDeque是JDK1.7版本加入的
Deque<String> deque=new ConcurrentLinkedDeque<String>();
deque.push("1");
deque.push("2");
deque.push("3");
deque.push("4");
deque.push("5");
System.out.println(deque);
System.out.println("---------------------------------------");
Queue<String> view = Collections.asLifoQueue(deque);
System.out.println(deque.remove());
System.out.println(deque.remove());
view.add("6");
view.add("7");
view.add("8");
System.out.println(deque);
System.out.println(view);
System.out.println("---------------------------------------");
System.out.println(view.remove());
System.out.println(view.remove());
}
}
查看java.util.Collections.asLifoQueue(Deque<T>)的返回值是一个后进先出的队列,具体实现:
public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
return new AsLIFOQueue<>(deque);
}
接下来看看AsLIFOQueue类结构:
static class AsLIFOQueue<E> extends AbstractQueue<E>
implements Queue<E>, Serializable {
private static final long serialVersionUID = 1802017725587941708L;
private final Deque<E> q;
AsLIFOQueue(Deque<E> q) { this.q = q; }
public boolean add(E e) { q.addFirst(e); return true; }
public boolean offer(E e) { return q.offerFirst(e); }
public E poll() { return q.pollFirst(); }
省略其余代码
}
无非又是代理模式,只不过这次允许add等操作了!!!
接下来研究方法:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
说明:
使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过 sort(List)
方法)。如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
package com.daxin.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main7 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
list.add(i);
}
// 注意:1:list必须是有序的,而且对于查到的元素类型必须实现Comparable接口才能进行比较。
//如果查询到的话就返回当前的索引号
System.out.println(Collections.binarySearch(list, 3));
// 如果没有查询到的话,返回-(插入点+1)的位置,例如:如果查询key不存在的话,如果正常向有序序列插入key时候应该插入的位置是i的话,那么不存返回的就是-(i+1)
System.out.println(Collections.binarySearch(list, 0));
System.out.println(Collections.binarySearch(list, -1));
System.out.println(Collections.binarySearch(list, 6));
System.out.println(Collections.binarySearch(list, 8));
//6+2的二进制向右移动1位变成4
// >>> : 无符号右移,忽略符号位,空位都以0补齐
// System.out.println((2-6) >>> 1);
// >> : 右移运算符,num >> 1,相当于num除以2
// System.out.println((2-6) >> 1);
}
接下来看java.util.Collections.binarySearch(List<? extends Comparable<? super T>>, T)的实现:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)//根据集合是否支持随机访问采用不同的随机查找
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
我们首先先查看java.util.Collections.indexedBinarySearch(List<? extends Comparable<? super T>>, T)的实现:
应该重点学习,以便自己实现二分查找:
private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;//忽略符号位右移1位,就是除以2
Comparable<? super T> midVal = list.get(mid);//获取中间值
int cmp = midVal.compareTo(key);//比较大小
if (cmp < 0)//小于的话,low向mid右移动
low = mid + 1;
else if (cmp > 0)//大于的话,high向mid左边移1位
high = mid - 1;
else
return mid; // key found //相等直接返回id
}
return -(low + 1); // key not found
}
接下来看没有实现RandomAccess的迭代器二分查找,其实也是根据索引实现的二分查找:
private static <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = get(i, mid);//重点方法:通过给定的迭代器查询第i个元素
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
get方法实现:
/**
* Gets the ith element from the given list by repositioning the specified
* list listIterator.
*/
private static <T> T get(ListIterator<? extends T> i, int index) {
T obj = null;
int pos = i.nextIndex();//获取当前元素位置
if (pos <= index) {//当前位置小于index位置
do {
obj = i.next();
} while (pos++ < index);
} else {//当前位置大于index位置
do {
obj = i.previous();
} while (--pos > index);
}
return obj;//最后返回
}
这也就是迭代器的二分查找。
二分查找还可以自己传入自定义的Comparator比较器:
public static <T> int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)
package com.daxin.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class User {
public User(int age) {
super();
this.age = age;
}
public User() {
super();
}
int age;
}
class UserComparator implements Comparator<User> {
@Override
public int compare(User o1, User o2) {
return o1.age - o2.age;
}
}
public class Main8 {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<User>();
for (int i = 1; i <= 5; i++) {
list.add(new User(i));
}
// 二分查找list必须是有序的
System.out.println(Collections.binarySearch(list, new User(2), new UserComparator()));
}
}
具体实现此处不讲解了。
还有自定义类实现Comparable<T>的示例如下:
package com.daxin.collections;
import java.util.ArrayList;
import java.util.Collections;
class Dog implements Comparable<Dog>{
int age ;
public Dog(int age) {
super();
this.age = age;
}
public Dog() {
super();
// TODO Auto-generated constructor stub
}
@Override
public int compareTo(Dog o) {
// TODO Auto-generated method stub
return this.age-o.age;
}
}
public class Main9 {
public static void main(String[] args) {
ArrayList<Dog> list = new ArrayList<Dog>();
for (int i = 1; i <= 5; i++) {
list.add(new Dog(i));
}
// 二分查找list必须是有序的
System.out.println(Collections.binarySearch(list, new Dog(2)));
}
}
此篇暂时到此结束。。。