jdk1.8包含的常用集合工具类,一般包括两个:
数组工具类:`java.util.Arrays `
结合工具类:`java.util.Collections`

今天就结合源码对`java.util.Arrays `的功能进行总结说明。

1、排序方法 `sort`


  • 8种基本类型数组排序

方法直接调用`java.util.DualPivotQuicksort`(双轴快速排序类)的相关方法进行排序。
而在该类的内部,又根据数组的大小和有序性的好坏,选择适合的排序算法。比如数组小于指定阈值,则采用使用双轴快排,如果顺序连续性好,直接使用TimSort算法,顺序连续性不好的数组直接使用了 双轴快排 + 成对插入排序。具体过程本文不叙述。可以参考:

双轴排序

  • object[]数组排序

对对象类型的数组的排序,其过程又有别于基本类型,jdk会借助于参数:LegacyMergeSort.userRequested
进行排序算法的选择,如果开启,那么采用传统的归并排序,否则采用[TimSort]的算法。

  • 并行排序方法`parallelSort`

parallelsort会把array分成不同的子数组,每个子数组用sort进行排序,最后再合并排序;整个过程用ForkJoin 
common pool(java.util.concurrent.ForkJoinPool)进行并发操作

2、并行累积方法`parallelPrefix`


使用提供的函数并行累积给定数组中的每个元素。例如,如果数组最初保存[2, 1, 0, 3]并且操作执行加法,则返回时数组成立[2, 3, 3, 6]。并行前缀计算通常比大型数组的顺序循环更有效。

    public static int[] intArrays ={55,45,23,11,10,88,102,99};

    public static void parallelPrefix(){

        System.out.println("*******调用前*******");
System.out.println(Arrays.toString(intArrays)); Arrays.parallelPrefix(intArrays,(x,y)->(x+y)); System.out.println("*******调用后*******");
System.out.println(Arrays.toString(intArrays));
}
 *******排序前*******
[55, 45, 23, 11, 10, 88, 102, 99]
*******排序后*******
[55, 100, 123, 134, 144, 232, 334, 433]
55=55
100=55+45
123=55+45+23
...
433=55+...+99

3、二叉查找`binarySearch`


在已排序数组中,找出指定值的元素所在的位置(如果为正数,返回从0开始的index,如果为负数,其绝对值-1为所找key最近的数组元素)。

     private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1; while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid]; if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}

4、相等性判断`equals`


数组等于比较,过程相对简单:

     public static boolean equals(int[] a, int[] a2) {
//同一个对象,即引用地址一样
if (a==a2)
return true;
//一个为null
if (a==null || a2==null)
return false;
//长度不等,直接返回
int length = a.length;
if (a2.length != length)
return false;
//每个元素比较,有不同就返回
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false; return true;
}

5、批量赋值`fill`


填充数据指定或者全部位置的值为指定值,相对简单。

     public static void fill(long[] a, long val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}

6、复制`copyOf`


对数组元素进行复制,其中返回的是一个新的数组,但是数组元素还是对原先数组堆对象的引用(即元素浅复制)。
该方法底层调用的是native方法,进行快速复制:`system.arraycopy`

 //测试示例
ArraysDemo[] demos ={new ArraysDemo("a"),new ArraysDemo("b"),new ArraysDemo("c"),new ArraysDemo("d"),new ArraysDemo("e")}; ArraysDemo[] newDemos = Arrays.copyOf(demos,demos.length); //数组对象深复制 返回false
System.out.println(demos==newDemos);
//数组元素浅复制,元素引用的还是同一个地址,返回true
System.out.println(demos[1]==newDemos[1]); newDemos[0] = new ArraysDemo("f");
//地址改变 返回false
System.out.println(demos[0]==newDemos[0]);
//元素内容改变
newDemos[1].setClassVer("bb");
//原始对象同时改变 打印bb
System.out.println(demos[1].getClassVer());

7、范围复制`copyOfRange`


数组的局部复制,最终调用6的copyOf方法。

8、返回集合`asList`


返回Arrays内部类ArrayList<>对象

private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable

相比较于java.util.ArrayList,缺少List接口的相关方法。

``` public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

所以List接口的相关方法无法调用。正如《阿里巴巴java开发规约》所描述的:

使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。
asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法,只是转换接口,后台数据仍旧是数组。

     public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
} //测试,异常 UnsupportedOperationException
List list = Arrays.asList(intArrays);
list.add(2);

其实asList内部是调用了抽闲类AbstractList的add方法,但内部类并没有重载实现。
所以:

     public void add(int index, E element) {
throw new UnsupportedOperationException();
}

9、hash计算`hashCode`


获取数组的hashcode,其内部是数组元素的hashcode的拼装,根据类型不同又有不同的拼装方式。

10、并行遍历迭代器`spliterator`


Spliterator可以理解为Iterator的Split版本(但用途要丰富很多)。使用Iterator的时候,我们可以顺序地遍历容器中的元素,使用Spliterator的时候,我们可以将元素分割成多份,分别交于不于的线程去遍历,以提高效率。使用 Spliterator 每次可以处理某个元素集合中的一个元素 — 不是从 Spliterator 中获取元素,而是使用 tryAdvance() 或 forEachRemaining() 方法对元素应用操作。但Spliterator 还可以用于估计其中保存的元素数量,而且还可以像细胞分裂一样变为一分为二。这些新增加的能力让流并行处理代码可以很方便地将工作分布到多个可用线程上完成。

11、流式处理`stream`


     public static void stream(){
String [] strArray = new String[] {"a", "b", "c","d"}; //过滤操作,过滤掉为a的字符串
List afterFilterLists =Arrays.stream(strArray).filter(s -> !s.equals("a"))
.collect(Collectors.toList()); System.out.println(afterFilterLists);
//输出[b, c, d] //foreach操作 输出 a b c d
Arrays.stream(strArray).forEach(s-> System.out.println(s)); }

JDK1.8源码泛读之Arrays的更多相关文章

  1. JDK1.8源码(四)——java.util.Arrays类

    一.概述 1.介绍 Arrays 类是 JDK1.2 提供的一个工具类,提供处理数组的各种方法,基本上都是静态方法,能直接通过类名Arrays调用. 二.类源码 1.asList()方法 将一个泛型数 ...

  2. 【集合框架】JDK1.8源码分析之Collections && Arrays(十)

    一.前言 整个集合框架的常用类我们已经分析完成了,但是还有两个工具类我们还没有进行分析.可以说,这两个工具类对于我们操作集合时相当有用,下面进行分析. 二.Collections源码分析 2.1 类的 ...

  3. JDK1.8源码(四)——java.util.Arrays 类

    java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名Arrays调用. 1.asList public static ...

  4. AQS源码泛读,梳理设计流程(jdk8)

    一.AQS介绍 AQS(AbstractQueuedSynchronizer)抽象队列同步器,属于多线程编程的基本工具:JDK对其定义得很详细,并提供了多种常用的工具类(重入锁,读写锁,信号量,Cyc ...

  5. JDK1.8源码学习-String

    JDK1.8源码学习-String 目录 一.String简介 String类是Java中最常用的类之一,所有字符串的字面量都是String类的实例,字符串是常量,在定义之后不能被改变. 二.定义 p ...

  6. 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)

    一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...

  7. JDK1.8源码阅读系列之三:Vector

    本篇随笔主要描述的是我阅读 Vector 源码期间的对于 Vector 的一些实现上的个人理解,用于个人备忘,有不对的地方,请指出- 先来看一下 Vector 的继承图: 可以看出,Vector 的直 ...

  8. 【集合框架】JDK1.8源码分析之ArrayList详解(一)

    [集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...

  9. 【1】【JUC】JDK1.8源码分析之ArrayBlockingQueue,LinkedBlockingQueue

    概要: ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞 注意这两个Condition即ReentrantLock的Co ...

随机推荐

  1. Android 解决adb server is out of date. killing... ADB server didn't ACK * failed to star

    The connection to adb is down, and a severe error has occured. [-- :: - HelloOPone] You must restart ...

  2. [ldap]ldap相关问题

    背景: ldap数据库要同步,按照如下操作步骤: 1.导出: 使用slapcat,slapcat直接对数据库操作, slapcat 2.将所需的条目取出,生成文件in.ldif 3.在目标机器上导入: ...

  3. udhcpd源码分析2--读取配置文件

    1:重要的结构体 读取配置文件信息到全局的结构体struct server_config_t server_config中,这个结构在很多文件中都有引用到很重要. /* dhcpd.h */ stru ...

  4. bzoj 1520 [POI2006]Szk-Schools 费用流

    [POI2006]Szk-Schools Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 743  Solved: 381[Submit][Status][ ...

  5. bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心

    [Apio2009]CONVENTION会议中心 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1130  Solved: 444[Submit][S ...

  6. ACM1598并查集方法

    find the most comfortable road Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Struc ...

  7. Intellij IDEA 使用jrebel运行spring-boot并实现自动编译进行热部署

    在使用jrebel运行spring-boot的时候,会发现一个很棘手的问题,就是项目不能自动编译,不能自动编译就不能实现热部署.(使用jar包方式运行的时候) 那么我们就要解决自动编译的问题,首先: ...

  8. 图论:最短路-Bellman-Ford

    我们之前介绍了一种,(最常用的)SPFA算法,SPFA算法是对Bellman-Ford算法的队列优化,用队列替代了Bellman-Ford中的循环检查部分 然后这里我们介绍Bellman-Ford算法 ...

  9. LightOJ 1013 - Love Calculator LCS

    题意:找一个串使给出的两个串都是它的子串,要求最短,求出最短长度,以及种类数. 思路:可以想到,当两个子串a,b拥有最长的公共子串为LCS时,那么可以求出的最短的串为lena+lenb-LCS. 那么 ...

  10. Sass 基本函数

    Sass 中的常用函数 一.字符串函数 1. unquote($string): 删除字符串前后的引号,删除一对引号,如果这个字符串没有带有引号,将返回原始的字符串. 示例: .text1 { con ...