Java之Collections工具类方法使用以及源码分析(二)

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)));
	}
	

}



此篇暂时到此结束。。。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值