java array 方法_Java的Arrays方法分析

2023-05-16

文章结构概览

本文将按一下顺序,逐一介绍。Arrays类介绍

Arrays方法分类排序相关

查找相关

比较相关

打印相关

计算hashCode

拷贝相关

赋值相关

转化为集合List

1. Arrays类介绍This class contains various methods for manipulating arrays (such as

sorting and searching). This class also contains a static factory

that allows arrays to be viewed as lists.

该类包含用于操作数组的各种方法(例如排序和搜索)。该类还包含一个静态工厂,允许将数组视为列表。

根据注释解释,可以知道该类是一个操作数组的工具类,里面封装了常用的数组操作方法。List相关类Arrays相关类图

2. Arrays方法分类

2.1 排序相关

2.1.1 普通排序

int[] numbers = new int[]{2, 8, 1};

// 整体排序System.out.println(Arrays.toString(numbers));

Arrays.sort(numbers);

System.out.println(Arrays.toString(numbers));

// 指定位置排序System.out.println(Arrays.toString(numbers));

Arrays.sort(numbers, 1, 2);

System.out.println(Arrays.toString(numbers));

主要是调用静态方法 sort() ,支持基本类型数组,引用类型数组必须实现 Comparable接口。

其中的排序算法用的是Dual-Pivot Quicksort(双轴快排),升序排序,时间复杂度为O(n log(n))。

/*** Sorts the specified range of the array using the given* workspace array slice if possible for merging** @param a the array to be sorted* @param left the index of the first element, inclusive, to be sorted* @param right the index of the last element, inclusive, to be sorted* @param work a workspace array (slice)* @param workBase origin of usable space in work array* @param workLen usable size of work array*/

static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) {

// 对于小规模的数组,使用快排 if (right - left < QUICKSORT_THRESHOLD) {

sort(a, left, right, true);

return;

}

/** Index run[i] is the start of i-th run* 索引从i开始* (升序或降序).*/

int[] run = new int[MAX_RUN_COUNT + 1];

int count = 0; run[0] = left;

// 检查数组是否接近有序 for (int k = left; k < right; run[count] = k) {

if (a[k] < a[k + 1]) { // 升序 while (++k <= right && a[k - 1] <= a[k]);

} else if (a[k] > a[k + 1]) { // 降序 while (++k <= right && a[k - 1] >= a[k]);

for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {

int t = a[lo]; a[lo] = a[hi]; a[hi] = t;

}

} else { // 相等 for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {

if (--m == 0) {

sort(a, left, right, true);

return;

}

}

}

/** 如果数组的规模没有超过最大规模,* 应该使用快排,而不是归并排序*/

if (++count == MAX_RUN_COUNT) {

sort(a, left, right, true);

return;

}

}

// 检查特殊情况 // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // 最后一次运行只包含一个元素 run[++count] = right;

} else if (count == 1) { // 数组已经有序 return;

}

// Determine alternation base for merge byte odd = 0;

for (int n = 1; (n <<= 1) < count; odd ^= 1);

// 创建或使用临时数组b int[] b; // temp array; alternates with a int ao, bo; // array offsets from 'left' 相对于left的偏移 int blen = right - left; // space needed for b b所需要的空间 if (work == null || workLen < blen || workBase + blen > work.length) {

work = new int[blen];

workBase = 0;

}

if (odd == 0) {

System.arraycopy(a, left, work, workBase, blen);

b = a;

bo = 0;

a = work;

ao = workBase - left;

} else {

b = work;

ao = 0;

bo = workBase - left;

}

// 合并排序 for (int last; count > 1; count = last) {

for (int k = (last = 0) + 2; k <= count; k += 2) {

int hi = run[k], mi = run[k - 1];

for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {

if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {

b[i + bo] = a[p++ + ao];

} else {

b[i + bo] = a[q++ + ao];

}

}

run[++last] = hi;

}

if ((count & 1) != 0) {

for (int i = right, lo = run[count - 1]; --i >= lo;

b[i + bo] = a[i + ao]

);

run[++last] = right;

}

int[] t = a; a = b; b = t;

int o = ao; ao = bo; bo = o;

}

}

2.1.2 并行排序

int[] numbers = new int[]{2, 8, 1};

// 整体排序System.out.println(Arrays.toString(numbers));

Arrays.parallelSort(numbers);

System.out.println(Arrays.toString(numbers));

// 指定位置排序System.out.println(Arrays.toString(numbers));

Arrays.parallelSort(numbers, 1, 2);

System.out.println(Arrays.toString(numbers));

主要是调用静态方法 parallelSort() ,支持基本数据类型数组,引用类型的数组需要实现Comparable接口,或者调用方法时传入指定的比较器。

这种排序方式,会去判断当前数组的大小是否 小于最小的并行排序长度 MIN_ARRAY_SORT_GRAN,或者并行池的数量为1,如果满足条件,还会调用Dual-Pivot Quicksort(双轴快排)方法来排序,否则才去执行并行排序。

public static void parallelSort(int[] a, int fromIndex, int toIndex) {

rangeCheck(a.length, fromIndex, toIndex);

int n = toIndex - fromIndex, p, g;

if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1) {

DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);

} else {

new ArraysParallelSortHelpers.FJInt.Sorter

(null, a, new int[n], fromIndex, n, 0,

((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?

MIN_ARRAY_SORT_GRAN : g).invoke();

}

}

2.2 查找相关

int[] numbers = new int[]{2, 8, 1};

// 整体查找int index = Arrays.binarySearch(numbers, 8);

System.out.println("8的对应下标为 " + index);

// 指定位置查找int index2 = Arrays.binarySearch(numbers, 8, 1, 2);

System.out.println("8的对应下标为 " + index2);

主要是调用静态方法 binarySearch() ,支持基本数据类型数组,引用类型的数组需要实现Comparable接口,或者调用方法时传入指定的比较器。

查找算法使用的是二分查找。

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.}

2.3 比较相关

2.3.1 普通比较

比较数组是否相等:

int[] numbers1 = new int[]{2, 8, 1};

int[] numbers2 = new int[]{2, 6, 1};

// 比较数组是否相等boolean result = Arrays.equals(numbers1, numbers2);

System.out.println("两个数组是否相等 " + result);

支持所有数据类型,其中引用类型会调用equals方法,如果没有重写,则比较的是地址值。

2.3.2 深度比较

针对引用类型,会比较该对象里的所有基本数据类型,如果全部相等,才对比成功。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers1 = new A[]{new A(1), new A(8), new A(0)};

A[] numbers2 = new A[]{new A(2), new A(8), new A(0)};

// 比较数组是否相等boolean result = Arrays.deepEquals(numbers1, numbers2);

System.out.println("两个数组是否相等 " + result);

2.4 打印相关

2.4.1 普通打印

将数组打印出来:

int[] numbers1 = new int[]{2, 8, 1};

// 打印数组System.out.println(Arrays.toString(numbers1));

支持所有数据类型,其中引用类型会调用 toString 方法。

2.4.2 深度打印

针对引用类型,会把该对象里的所有基本数据类型打印出来。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(8), new A(0)};

// 打印数组System.out.println(Arrays.deepToString(numbers));

2.5 计算hashCode

2.5.1 普通计算

int[] numbers1 = new int[]{2, 8, 1};

// 打印数组的hash值System.out.println("hashCode " + Arrays.hashCode(numbers1));

支持所有数据类型,其中引用类型会调用 hashCode 方法。

2.5.2 深度计算

针对引用类型,会计算该对象里的所有基本数据类型的hashCode。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(8), new A(0)};

// 打印数组的hash值System.out.println("hashCode " + Arrays.deepHashCode(numbers));

2.6 拷贝相关

// 整体拷贝int[] numbers = new int[]{2, 8, 1};

int[] numbers2 = Arrays.copyOf(numbers, 8);

// 打印拷贝的数组System.out.println(Arrays.toString(numbers2));

// 局部拷贝int[] numbers3 = Arrays.copyOfRange(numbers, 1, 8);

System.out.println(Arrays.toString(numbers3));

其中 copyOf 和 copyOfRange 都会调用 System的一个静态方法 arraycopy,如下所示。

public static void arraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {

if (src == null) {

throw new NullPointerException("src == null");

}

if (dst == null) {

throw new NullPointerException("dst == null");

}

if (srcPos < 0 || dstPos < 0 || length < 0 ||

srcPos > src.length - length || dstPos > dst.length - length) {

throw new ArrayIndexOutOfBoundsException(

"src.length=" + src.length + " srcPos=" + srcPos +

" dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length);

}

if (length <= ARRAYCOPY_SHORT_INT_ARRAY_THRESHOLD) {

// Copy int by int for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) {

// Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) {

dst[dstPos + i] = src[srcPos + i];

}

} else {

// Copy forward. for (int i = 0; i < length; ++i) {

dst[dstPos + i] = src[srcPos + i];

}

}

} else {

// Call the native version for longer arrays. arraycopyIntUnchecked(src, srcPos, dst, dstPos, length);

}

}

2.7 赋值相关

可以为一个数组赋上初始值。

// 整体赋值int[] numbers = new int[9];

Arrays.fill(numbers, 8);

System.out.println(Arrays.toString(numbers));

// 局部赋值int[] numbers2 = new int[9];

int value = 9;

Arrays.fill(numbers2, 5, 8, value);

System.out.println(Arrays.toString(numbers2));

2.8 转换为集合List

将一个数组转换成一个List。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(2)};

List list = Arrays.asList(numbers);

需要注意的是 该List是 Arrays的一个内部类,并不是我们常用的 ArrayList。

并且其只实现了部分方法:Arrays内部的List中实现的方法

调用其他方法 会抛出异常 UnsupportedOperationException。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java array 方法_Java的Arrays方法分析 的相关文章

  • 是什么决定了从 lambda 创建哪个函数式接口?

    请考虑这个例子 import java util function Consumer public class Example public static void main String args Example example new
  • org.apache.sling.api.resource,version=[2.3,3) -- 无法解析

    您好 我无法访问我的项目内容 我已经上传了从 CQ 访问内容所需的所有包 我唯一能看到的是 org apache sling api resource version 2 3 3 无法解析 这是否是异常的原因 如果是 请告诉我如何解决 中Q
  • 正则表达式拆分数字和字母组,不带空格

    如果我有一个像 11E12C108N 这样的字符串 它是字母组和数字组的串联 如何在中间没有分隔符空格字符的情况下分割它们 例如 我希望分割结果为 tokens 0 11 tokens 1 E tokens 2 12 tokens 3 C
  • JAVA - Xuggler - 组合 MP3 音频文件和 MP4 电影时播放视频

    使用 JAVA 和 Xuggler 以下代码组合 MP3 音频文件和 MP4 电影文件并输出组合的 mp4 文件 我希望在合并音频和视频文件时应自动播放输出视频文件 String inputVideoFilePath in mp4 Stri
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht
  • 按第一列排序二维数组,然后按第二列排序

    int arrs 1 100 11 22 1 11 2 12 Arrays sort arrs a b gt a 0 b 0 上面的数组已排序为 1 100 1 11 2 12 11 22 我希望它们按以下方式排序a 0 b 0 首先 如果
  • 在 Netbeans 8 上配置 JBoss EAP 的问题

    我已经下载了 JBoss EAP 7 并正在 Netbeans 8 上配置它 我已经到达向导 实例属性 其中要求从选择框中选择 域 当我打开选择框时 它是空的 没有什么可以选择的 因此 完成 按钮也处于非活动状态 这使得无法完成配置 我通过
  • Calendar.getInstance(TimeZone.getTimeZone("UTC")) 不返回 UTC 时间

    我对得到的结果真的很困惑Calendar getInstance TimeZone getTimeZone UTC 方法调用 它返回 IST 时间 这是我使用的代码 Calendar cal Two Calendar getInstance
  • 使用 SQLITE 按最近的纬度和经度坐标排序

    我必须获得一个 SQLite SQL 语句 以便在给定初始位置的情况下按最近的纬度和经度坐标进行排序 这是我在 sqlite 数据库中的表的例句 SELECT id name lat lng FROM items EXAMPLE RESUL
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • 如何知道抛出了哪个异常

    我正在对我们的代码库进行审查 有很多这样的陈述 try doSomething catch Exception e 但我想要一种方法来知道 doSomething 抛出了哪个异常 在 doSomething 的实现中没有 throw 语句
  • 在 Spring 中重构这个的最佳方法?

    private final ExecutorService executorParsers Executors newFixedThreadPool 10 public void parse List
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • javafx android 中的文本字段和组合框问题

    我在简单的 javafx android 应用程序中遇到问题 问题是我使用 gradle javafxmobile plugin 在 netbeans ide 中构建了非常简单的应用程序 其中包含一些文本字段和组合框 我在 android
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • ServletContainer 类未找到异常

    我无法再编译我的球衣项目 并且出现以下异常 GRAVE Servlet Project API threw load exception java lang ClassNotFoundException com sun jersey spi
  • 调整添加的绘制组件的大小和奇怪的摆动行为

    这个问题困扰了我好几天 我正在制作一个特殊的绘画程序 我制作了一个 JPanel 并添加了使用 Paint 方法绘制的自定义 jComponent 问题是 每当我调整窗口大小时 所有添加的组件都会 消失 或者只是不绘制 因此我最终会得到一个
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话

随机推荐