当前位置: 首页 > 后端技术 > Java

Java.util.Arrays参考指南

时间:2023-04-02 00:00:28 Java

1.简介在本文中,我们将了解java.util.Arrays。这是自Java1.2以来就存在的Java实用程序类。使用数组,我们可以创建、比较、排序、搜索、流操作和其他转换操作。二、创建让我们看一下通过Arrays创建数组的方法:copyOf、copyOfRange和fill。2.1.copyOf和copyOfRange要使用copyOfRange,我们需要一个源数组和起始索引和结束索引,前闭后开:String[]intro=newString[]{"once","upon","a","time"};String[]abridgement=Arrays.copyOfRange(intro,0,3);assertArrayEquals(newString[]{"once","upon","a"},abridgement);assertFalse(Arrays.equals(intro,删节));使用copyOf,需要传入一个源数组和目标数组的长度,并返回一个新数组,新数组的长度就是传入参数的长度:String[]intro=newString[]{"once","upon","a","time"};String[]revised=Arrays.copyOf(intro,3);String[]expanded=Arrays.copyOf(intro,5);assertArrayEquals(Arrays.copyOfRange(intro,0,3),修订版);assertNull(扩展[4]);注意:copyOf后,如果返回数组的长度大于源数组的长度,将使用null值填充剩余空间。2.2.fill另一种方法,我们可以使用fill创建一个固定长度的数组,当所有数组元素都相同时非常有用:String[]stutter=newString[3];Arrays.fill(stutter,"once");assertTrue(Stream.of(stutter).allMatch(el->"once".equals(el));setAll是创建一个不同元素的数组注意:我们需要在调用fill之前提前初始化数组三、现在比较3.1.equals和deepEquals我们可以使用equals对数组的大小和内容进行简单的比较,如果我们在数组中加入一个空元素,则两个数组是不相等。String[]intro=newString[]{"once","upon","a","time"};assertTrue(Arrays.equals(newString[]{"once","upon","a",“时间”},简介));assertFalse(Arrays.equals(newString[]{"一次","upon","a","null"},简介));如果我们比较嵌套或多维数组,我们可以使用deepEquals不仅可以比较第一级元素,还可以递归比较对象元素:String[]end=newString[]{"end"};String[]intro=newString[]{“once”,“upon”,“a”,“time”};Object[]story=newObject[]{intro,newString[]{“chapterone”,“chaptertwo”},end};Object[]copy=newObject[]{intro,newString[]{"chapterone","chaptertwo"},end};assertTrue(Arrays.deepEquals(story,copy));assertFalse(Arrays.equals(story,copy));以上代码,deepEquals返回true,equals返回false。这是因为deepEquals每次比较时都会调用自己,而equals只比较对子数组的引用。因此,使用自引用数组的调用是非常危险的。3.2.hashCode_and_deepHashCode我们使用hashCode方法根据对象的内容计算一个整数:Object[]looping=newObject[]{intro,intro};inthashBefore=Arrays.hasCode(looping);intdeepHashBefore=Arrays.deepHashCode(循环);现在,我们将数组中的一个元素设为null并检索其哈希值intro[3]=null;inthashAfter=Arrays.hashCode(looping);让我们再次尝试deepHashCode,它会检查每个元素的内容。让我们再次调用它:intdeepHashAfter=Arrays.deepHashCode(looping);现在,让我们看看这两种方法之间的一些区别:assertEquals(hashAfter,hashBefore);assertNotEquals(deepHashAfter,deepHashBefore);deepHashCode就是我们在HashMap和HashSet等数据结构作为数组元素时进行的低级操作。4.排序和搜索让我们看一下数据排序和搜索4.1。sort如果我们的元素是实现Compareable的基本元素或者对象,我们可以使用sort来排序:String[]sorted=Arrays.copyOf(intro,4);Arrays.sort(sorted);assertArrayEquals(newString[]{"a","once","time","upon"},sorted);排序根据数组算法使用不同的元素类型。基本类型使用双轴快速排序,对象类型数组使用Timsort。两者的时间复杂度都是O(nlog(n))。4.2.binarySearch在未排序的数组中是线性的,但是如果是排序的数组,我们可以使用二分查找在O(logn)中完成:intexact=Arrays.binarySearch(sorted,"time");intcaseInsensitive=Arrays.binarySearch(排序,“时间”,字符串::compareToIgnoreCase);assertEquals(“时间”,排序[精确]);assertEquals(2,精确);assertEquals(精确,caseInsensitive);如果我们不提供comparator作为前三个参数,那么binarySearch将取决于我们的元素类型的Comparable。再次注意,使用binarySearch的前提是数组已经排好了序。5.Stream操作前面提到,Java8更新了Arrays,提供了StreamAPI方法,如parallelSort、stream、setAll。5.1.stream方法让我们调用StreamAPI来像流一样使用我们的数组:Assert.assertEquals(Arrays.stream(intro).count(),4);exception.expect(ArrayIndexOutOfBoundsException.class);Arrays.stream(intro,2,1).计数();我们可以传入范围内的索引或者范围外的索引,超出范围就会抛出ArrayindexOutOfBoundsException。六、转换最后,toString、asList和setAll为我们提供了几种不同的数组转换方式。6.1.toString和deepToString将基本类型的数组转换为字符串的一种良好且可读的方法:assertEquals("[once,upon,atime]",Arrays.toString(storyIntro));同样,我们也可以使用deepToSTRing来打印对象类型数组:assertEquals([[once,upon,a,time],[chapterone,chaptertow],[the,end]]",Arrays.deepToString(story));6.2。asListArrays最方便的方法之一是asList,它将数组转换为列表:Listrets=Arrays.asList(intro);assertTrue(rets.contains("upon"));assertTrue(rets.contains("时间"));assertEquals(rets.size(),4);但是,返回的List将是固定长度的,因此我们无法添加或删除元素。注意:java.util.Arrays的asList方法返回它自己的ArrayList子类。6.3.setAll使用setAll设置生成器来初始化数组的元素:String[]longAgo=newString[4];Arrays.setAll(longAgo,i->intro[i]);assertArrayEquals(longAgo,newString[]{"很久以前”});使用lambda表达式也极易出现异常。7.ParallelPrefixArraysJava8引入的另一个新方法是parallelPrefix。使用parallelPrefix,我们可以以累积方式对输入数组的每个元素进行操作。7.1.parallelPrefix像[1,2,3,4]一样进行累加运算,输出结果[1,3,6,10]:int[]arr=newint[]{1,2,3,4};Arrays。parallelPrefix(arr,(left,right)->left+right);assertThat(arr,is(newint[]{1,3,6,10}));我们还可以指定一个范围:int[]arr=newint[]{1,2,3,4,5};Arrays.parallelPrefix(arr,1,4,(left,right)->left+right);assertThat(arr,is(newint[]{1,2,5,9,5}));注意:由于此方法是并行执行的,因此累积操作应该是无状态的。对于非关联函数:intnonassociativeFunc(intleft,intright){returnleft+right*left;}下面会产生不一致:@TestpublicvoidwhenPrefixNonAssociative_thenError(){booleanconsistent=true;随机数r=newRandom();对于(intk=0;k<100_000;k++){int[]arrA=r.ints(100,1,5).toArray();int[]arrB=Arrays.copyOf(arrA,arrA.length);Arrays.parallelPrefix(arrA,this::nonassociativeFunc);对于(inti=1;ileft+right);blackhole.consume(bigArray.data);}8.总结我们在本文中学到的内容如何使用java.util.Arrays类创建、搜索、排序和转换数组的一些方法该类在最新的Java版本中得到了扩展,包括Java8中流的引入和Java9中的增强。