Java 8 增强的工具类:Arrays

Java 提供的 Arrays 类里包含了一些 static 修饰的方法 可以直接操作数组.(static 修饰的方法可以直接通过类名调用).Java 8 增强了Arrays类的功能,增加了一些工具方法,可以充分利用多CPU并行的能力来提高设值、排序的性能。
大致分为两类方法,一类是单线方法(用于单线程处理数组),另一类是多线算法(大多以parallel作为前缀,可以充分利用现代CPU多核并行的特点多线程处理数组,特别是对于那些规模非常庞大的数组);

单线程方法:

  • int binarySearch(type[] a,type key)
    使用二分法查询key元素值在a数组中出现的索引,如果a数组中不包含key元素值,则返回负数, 调用该方法是要求数组中元素已经按照升序排列,这样才能得到正确结果。
  • int binarySearch(type[] a ,type key,int fromIndex,int toIndex)
    重载上一个方法,增加了开始下标和结束下标,规定了查找的范围。调用该方法是要求数组中元素已经按照升序排列,这样才能得到正确结果。
private static int binarySearch0(long[] a, int fromIndex, int toIndex,long key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            long 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.
  }

获取任意类型的数组,一个对应类型的元素key,还有int类型的开始和结束下标,为了公用一个算法方法,我们先给定两个局部变量,如果没有指定开始和结束下标那么指定从0开始到数组a的长度-1结束。然后循环,循环判定条件是最小范围值小于等于最大范围值。然后中间值和key的比较,确定范围,最后确定key所在位置的index,直接返回。如果没有该值,直接返回负数。

  • type[] copyOf(type[] original,int length)
    复制original数组到一个新数组,length为新数组的长度,如果length的值大于original的长度,那么新数组的其他值补0(数值类型),false(布尔类型),null(引用类型)等。如果length的值小于original的长度,那么新数组就是origin数组前length个元素。
  • type[] copyOfRange(type[] original,int fromIndex,int toIndex)
    该方法是上面方法的重载,规定了开始复制的下标和结束复制的下标,也就是复制规定位置的数组元素到新数组中。
public static byte[] copyOf(byte[] original, int newLength) {
        byte[] copy = new byte[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
}
 
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

Java中这个方法是调用了System类中的arraycopy方法实现的,但是arraycopy有一个修饰符native.方法用native关键字修饰,说明该方法有实现,但不是使用java代码实现的,它的实现是在一个DLL文件中,可能使用C语言等其他语言实现,方便了java和硬件的交互,缺点是增加开销。Native方法也被称为本地方法。

public static byte[] copyOfRange(byte[] original, int from, int to) {
       int newLength = to - from;
       if (newLength < 0)
           throw new IllegalArgumentException(from + " > " + to);
       byte[] copy = new byte[newLength];
       System.arraycopy(original, from, copy, 0,
                        Math.min(original.length - from, newLength));
       return copy;
}

先计算出新数组的长度,使用结束下标-开始下标,如果小于0,说明结束下标小于开始下标,这样不成立,所以手动抛出异常。然后调用System类的arraycopy方法,执行。

  • boolean equals(long[] a1,long[] a2)
    判断两个数组的长度和内容是否相同(数组元素必须一一对应并相同)。
public static boolean equals(long[] a, long[] a2) {
       if (a==a2)
           return true;
       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;
}
  • void sort(type[] a)
    对数组进行排序
  • void sort(type[] a,int fromIndex,int toIndex)
    该方法是上面方法的重载,规定了开始复制的下标和结束复制的下标
  • String toString(type[] a)

多线方法:都以parallel作为前缀,表示并行计算

  • void parallelPrefix(type[] a, int from, int to, typeBinaryOperator op);
    i. 表示将数组a的[from, to)进行typeBinaryOperator的二元迭代;
    ii. 其中BinaryOperator就是二元操作符的意思;
    iii. 该方法的意思其实就是以下代码:
static void parallelPrefix(type[] a, int from, int to, TypeBinaryOperator op) {  
    for (int i = from; i < to; i++) {  
        type left = (i == 0)? 1: a[i - 1]; // 对于第一个元素left = 1  
        type right = a[i];  
        a[i] = left op right;  
    }  
}  

即从头到尾逐个按照left op right的方式更新,那更新后的值继续迭代下一个元素。

iv. 其中typeBinaryOperator表示二元运算法,type目前基本支持Java的基础类型(int、double等),该运算法其实是一个函数式接口,里面只有一个方法:

 public interface TypeBinaryOperator {   
      type applyAsInt(type left, type right);  
 }  

例如上面的如果想使用连乘迭代那就可以直接用Lambda表达式:Arrays.parallelPrefix(arr, 1, 5, (left, right) -> left * right);就行了;

  • void parallelPrefix(type[] a, typeBinaryOperator op);
    默认区间就是全部[0, length] == [0, length + 1);

如果是数组[1, 2, 3, 4, 5]进行全区间的连乘迭代,得到的结果就是[1, 2, 6, 24, 120];

  • void parallelSort(type[] a);
    对数组进行排序,与sort相同只是增加了并行能力,可以利用多CPU并行来提高性能。
  • void parallelSort(type[] a, int fromIndex, int toIndex);
    该方法是上面方法的重载,规定了开始下标和结束下标。
  • void parallelSetAll(type[] a, TypeUnaryOperator op);
    该方法就是用填充算法为数组a的每个元素赋值; UnaryOperator是一元运算符的意思,之所以是一元是因为该方法默认用元素的索引来生成该元素的值,该接口也是一个函数式接口:
public interface TypeUnaryOperator {  
  
    type applyAsInt(type operand); // 利用索引生成一个值,如何生成自己定义  
}  

该方法的意思就是:

static void parallelSetAll(Type[] a, TypeUnaryOperator op) {  
    for (int i = 0; i < a.length; i++) {  
        a[i] = op(i);  
    }  
}  

例如:Arrays.parallelSetAll(a, index -> index * 5); // 一个长度为5的int数组其填充结果就是[0, 5, 10, 15, 20]

  • XxxStream stream(xxx[] array)
    将数组转为流式,对array进行流式处理,可用一切流式处理的方法

      Arrays.stream(arrayTest)
              .map(a->a*2)
              .filter(a->a>10)
              .sorted()
              .distinct()
              .limit(6)
              .forEach(a-> System.out.print(a+" "));
      System.out.println();
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,253评论 0 16
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,771评论 1 10
  • 果果可怜的女儿欠欠静静地躺在冷棺里永远的睡去了,果果却毫无睡意,四年的婚姻生活把果果糟蹋得心力交瘁,起初郭靖只是夜...
    捡尽寒枝不肯栖阅读 175评论 0 0