当前位置: 首页 > 科技观察

详细讲解如何使用Java.util.Arrays

时间:2023-03-20 23:07:49 科技观察

大家好,我是北君。在本文中,我们将了解java.util.Arrays,我们可以使用Arrays来创建、比较、排序、搜索、流式传输和转换数组。创建让我们来看看如何使用Arrays创建一个新数组。一般来说,我们可以使用Arrays的copyOf、copyOfRange和fill方法。copyOf和copyOfRange要使用copyOfRange,我们需要一个原始数组和我们要复制的起始索引(含)和结束索引(不含)。让我们先定义一个数组介绍。String[]intro=newString[]{"once","upon","a","time"};String[]abridgement=Arrays.copyOfRange(storyIntro,0,3);assertArrayEquals(newString[]{"once","upon","a"},删节);assertFalse(Arrays.equals(介绍,删节));要使用copyOf,我们需要使用intro和一个目标数组大小,然后我们将得到一个新数组的长度。String[]revised=Arrays.copyOf(intro,3);String[]expanded=Arrays.copyOf(intro,5);assertArrayEquals(Arrays.copyOfRange(intro,0,3),revised);assertNull(expanded[4]);请注意,如果我们的目标大小大于原始大小,copyOf将用空值填充数组。填充我们可以创建固定长度数组的另一种方法是填充,当我们想要一个所有元素都相同的数组时,此方法很有用。String[]stutter=newString[3];Arrays.fill(stutter,"一次");assertTrue(Stream.of(stutter).allMatch(el->"once".equals(el));注意我们需要提前实例化数组,而不是像String[]filled=Arrays.fill("once",3);,因为这个特性是在语言出现泛型之前引入的。我们先来看一下Arrays的比较。方法equals和deepEquals我们可以使用equals来进行简单的数组大小和内容比较。如果我们添加一个null作为一个的元素,内容检查将失败。assertTrue(Arrays.equals(newString[]{"once","upon","a","time"},intro));assertFalse(Arrays.equals(newString[]{"once","upon","a",null},intro));当我们有嵌套或多维数组时,我们可以使用deepEquals不仅检查顶级元素,而且递归地执行检查。Object[]story=newObject[]{intro,newString[]{"第一章","第二章"},end};Object[]copy=newObject[]{intro,newString[]{"chapter一”,“第二章”},结束};assertTrue(Arrays.deepEquals(故事,copy));assertFalse(Arrays.equals(story,copy));请注意,这里传递了deepEquals,但equals失败了。这是因为deepEquals每次遇到数组时都会调用自己,而equals只是比较对子数组的引用。hashCode和deepHashCode我们使用hashCode根据数组Object[]的内容计算一个整数looping=newObject[]{intro,intro};inthashBefore=Arrays.hashCode(looping);intdeepHashBefore=Arrays.deepHashCode(looping);现在,我们将原始数组的一个元素设置为null并重新计算哈希。介绍[3]=null;inthashAfter=Arrays.hashCode(循环);deepHashCode检查嵌套数组的元素数量和内容是否匹配。如果我们用deepHashCode重新计算。intdeepHashAfter=Arrays.deepHashCode(looping);现在,我们可以看到这两种方法之间的区别。assertEquals(hashAfter,hashBefore);assertNotEquals(deepHashAfter,deepHashBefore);deepHashCode是我们在数组上使用HashMap、HashSet等数据结构时的基础计算。排序和搜索Sorting如果我们的元素是原始类型,或者如果它们实现了Comparable接口,我们可以使用sort来执行排序。String[]sorted=Arrays.copyOf(intro,4);Arrays.sort(sorted);assertArrayEquals(newString[]{"a","once","time","upon"},sorted);请注意,排序会更改原始引用,这就是我们在此处进行复制的原因。排序将针对不同的数组元素类型使用不同的算法。对原始类型使用快速排序,对对象类型使用Timsort。对于随机排序的数组,两者的平均情况都是O(nlog(n))。从Java8开始,parallelSort可用于并行排序,它提供了使用多个Arrays.sort任务的并发排序方法。如果我们有一个排序数组,搜索可以在O(logn)中完成,我们可以使用binarySearch来完成这样的任务。intexact=Arrays.binarySearch(sorted,"time");intcaseInsensitive=Arrays.binarySearch(sorted,"Time",String::compareToIgnoreCase);assertEquals("time",sorted[exact]);assertEquals(2,精确);assertEquals(精确,caseInsensitive);如果我们不提供比较器作为第三个参数,则binarySearch会假定我们的元素类型是可比较的。如果我们的数组没有首先排序,那么binarySearch将不会像我们预期的那样工作。我们都知道Java8更新了Arrays,包括StreamAPI的方法,比如parallelSort、stream、setAll。stream使我们能够完全访问数组的StreamAPI。Assert.assertEquals(Arrays.stream(intro).count(),4);exception.expect(ArrayIndexOutOfBoundsException.class);Arrays.stream(intro,2,1).count();我们可以提供包容性和独占性索引,但如果索引乱序、负数或超出范围,我们应该抛出ArrayIndexOutOfBoundsException。转换toString、asList和setAll为我们提供了几种不同的数组转换方式。toString和deepToString我们可以获得原始数组的可读版本的一种好方法是通过toString。assertEquals("[一次,一次,一次]",Arrays.toString(storyIntro));当数组嵌套时,我们必须再次使用deepToString来打印嵌套数组的内容。assertEquals("[[once,upon,a,time],[第一章,第二章],[the,end]]",Arrays.deepToString(story));在所有的数组方法中,asList是我们使用起来最方便的。就是asList。我们有一个简单的方法可以将数组转换为列表。Listrets=Arrays.asList(storyIntro);assertTrue(rets.contains("upon"));assertTrue(rets.contains("time"));assertEquals(rets.size(),4);returned列表将是固定长度的,不能添加或删除元素。另外需要注意的是asList会返回这个ArrayList的类型,和我们平时使用的ArrayList是不一样的。调试的时候可能会很骗人,在写的过程中一定要特别注意。setAll通过setAll,我们可以使用函数式接口来设置一个数组的所有元素。下面的代码现在将位置索引作为参数传递给getWord方法。String[]longAgo=newString[4];Arrays.setAll(longAgo,i->this.getWord(i));assertArrayEquals(longAgo,newString[]{"a","long","time","ago"});当然,异常处理是使用lambda的棘手部分之一。所以请记住,如果lambda抛出异常,Java不会定义数组的最终状态。