This commit is contained in:
Looly 2023-04-03 23:49:34 +08:00
parent 154192c7ee
commit 98d08dc00a
6 changed files with 233 additions and 113 deletions

View File

@ -13,9 +13,9 @@
package org.dromara.hutool.core.array;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.collection.iter.IterUtil;
import org.dromara.hutool.core.collection.set.SetUtil;
import org.dromara.hutool.core.collection.set.UniqueKeySet;
import org.dromara.hutool.core.collection.iter.IterUtil;
import org.dromara.hutool.core.comparator.CompareUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.exceptions.UtilException;
@ -27,7 +27,6 @@ import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.util.RandomUtil;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
@ -44,8 +43,8 @@ public class ArrayUtil extends PrimitiveArrayUtil {
/**
* 转为数组如果values为数组返回否则返回一个只有values一个元素的数组
*
* @param <A> 数组类型
* @param values 元素值
* @param <A> 数组类型
* @param values 元素值
* @return 数组
*/
public static <A> A ofArray(final Object values) {
@ -73,6 +72,34 @@ public class ArrayUtil extends PrimitiveArrayUtil {
return (A) newInstance;
}
/**
* 将集合转为数组
*
* @param <T> 数组元素类型
* @param iterator {@link Iterator}
* @param componentType 集合元素类型
* @return 数组
* @since 3.0.9
*/
public static <T> T[] ofArray(final Iterator<T> iterator, final Class<T> componentType) {
if (null == iterator) {
return newArray(componentType, 0);
}
return ListUtil.of(iterator).toArray(newArray(componentType, 0));
}
/**
* 将集合转为数组
*
* @param <T> 数组元素类型
* @param iterable {@link Iterable}
* @param componentType 集合元素类型
* @return 数组
* @since 3.0.9
*/
public static <T> T[] ofArray(final Iterable<T> iterable, final Class<T> componentType) {
return ofArray(IterUtil.getIter(iterable), componentType);
}
// ---------------------------------------------------------------------- isEmpty
/**
@ -474,7 +501,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* </ul>
*
* @param <A> 数组类型
* @param array 已有数组
* @param array 已有数组
* @param index 位置
* @param values 新值
* @return 新数组或原有数组
@ -1133,56 +1160,32 @@ public class ArrayUtil extends PrimitiveArrayUtil {
/**
* 获取子数组
*
* @param array 数组
* @param start 开始位置包括
* @param end 结束位置不包括
* @param array 数组
* @param beginInclude 开始位置包括
* @param endExclude 结束位置不包括
* @return 新的数组
* @since 4.0.6
* @param <A> 数组类型
*/
public static Object[] sub(final Object array, final int start, final int end) {
return sub(array, start, end, 1);
public static <A> A sub(final A array,
final int beginInclude, final int endExclude) {
return ArrayWrapper.of(array).getSub(beginInclude, endExclude);
}
/**
* 获取子数组
*
* @param array 数组
* @param start 开始位置包括
* @param end 结束位置不包括
* @param step 步进
* @param array 数组
* @param beginInclude 开始位置包括
* @param endExclude 结束位置不包括
* @param step 步进
* @return 新的数组
* @since 4.0.6
* @param <A> 数组类型
*/
public static Object[] sub(final Object array, int start, int end, int step) {
final int length = length(array);
if (start < 0) {
start += length;
}
if (end < 0) {
end += length;
}
if (start > end) {
final int tmp = start;
start = end;
end = tmp;
}
if (start >= length) {
return new Object[0];
}
if (end > length) {
end = length;
}
if (step <= 1) {
step = 1;
}
final List<Object> list = new ArrayList<>();
for (int i = start; i < end; i += step) {
list.add(get(array, i));
}
return list.toArray();
public static <A> A sub(final A array,
final int beginInclude, final int endExclude, final int step) {
return ArrayWrapper.of(array).getSub(beginInclude, endExclude, step);
}
/**
@ -1317,55 +1320,6 @@ public class ArrayUtil extends PrimitiveArrayUtil {
return StrJoiner.of(conjunction).append(array).toString();
}
/**
* {@link ByteBuffer} 转byte数组
*
* @param bytebuffer {@link ByteBuffer}
* @return byte数组
* @since 3.0.1
*/
public static byte[] toArray(final ByteBuffer bytebuffer) {
if (bytebuffer.hasArray()) {
return Arrays.copyOfRange(bytebuffer.array(), bytebuffer.position(), bytebuffer.limit());
} else {
final int oldPosition = bytebuffer.position();
bytebuffer.position(0);
final int size = bytebuffer.limit();
final byte[] buffers = new byte[size];
bytebuffer.get(buffers);
bytebuffer.position(oldPosition);
return buffers;
}
}
/**
* 将集合转为数组
*
* @param <T> 数组元素类型
* @param iterator {@link Iterator}
* @param componentType 集合元素类型
* @return 数组
* @since 3.0.9
*/
public static <T> T[] toArray(final Iterator<T> iterator, final Class<T> componentType) {
if (null == iterator) {
return newArray(componentType, 0);
}
return ListUtil.of(iterator).toArray(newArray(componentType, 0));
}
/**
* 将集合转为数组
*
* @param <T> 数组元素类型
* @param iterable {@link Iterable}
* @param componentType 集合元素类型
* @return 数组
* @since 3.0.9
*/
public static <T> T[] toArray(final Iterable<T> iterable, final Class<T> componentType) {
return toArray(IterUtil.getIter(iterable), componentType);
}
// ---------------------------------------------------------------------- remove
/**
@ -1688,7 +1642,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
final Set<T> set = new LinkedHashSet<>(array.length, 1);
Collections.addAll(set, array);
return toArray(set, (Class<T>) getComponentType(array));
return ofArray(set, (Class<T>) getComponentType(array));
}
/**
@ -1717,7 +1671,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
set.addIfAbsent(t);
}
}
return toArray(set, (Class<T>) getComponentType(array));
return ofArray(set, (Class<T>) getComponentType(array));
}
/**

View File

@ -7,6 +7,7 @@ import org.dromara.hutool.core.util.ObjUtil;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
@ -410,38 +411,141 @@ public class ArrayWrapper<A> implements Wrapper<A> {
/**
* 获取子数组
*
* @param begin 开始位置包括
* @param end 结束位置不包括
* @param beginInclude 开始位置包括
* @param endExclude 结束位置不包括
* @return 新的数组
* @see Arrays#copyOfRange(Object[], int, int)
* @since 4.2.2
*/
@SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"})
public A getSub(int begin, int end) {
public A getSub(int beginInclude, int endExclude) {
final int length = this.length;
if (begin < 0) {
begin += length;
if (beginInclude < 0) {
beginInclude += length;
}
if (end < 0) {
end += length;
if (endExclude < 0) {
endExclude += length;
}
if (begin > end) {
final int tmp = begin;
begin = end;
end = tmp;
if (beginInclude > endExclude) {
final int tmp = beginInclude;
beginInclude = endExclude;
endExclude = tmp;
}
if (begin >= length) {
if (beginInclude >= length) {
return (A) Array.newInstance(this.componentType, 0);
}
if (end > length) {
end = length;
if (endExclude > length) {
endExclude = length;
}
final A result = (A) Array.newInstance(this.componentType, end - begin);
System.arraycopy(this.array, begin, result, 0, end - begin);
final A result = (A) Array.newInstance(this.componentType, endExclude - beginInclude);
System.arraycopy(this.array, beginInclude, result, 0, endExclude - beginInclude);
return result;
}
/**
* 获取子数组
*
* @param beginInclude 开始位置包括
* @param endExclude 结束位置不包括
* @param step 步进
* @return 新的数组
*/
@SuppressWarnings("unchecked")
public A getSub(int beginInclude, int endExclude, int step) {
final int length = this.length;
if (beginInclude < 0) {
beginInclude += length;
}
if (endExclude < 0) {
endExclude += length;
}
if (beginInclude > endExclude) {
final int tmp = beginInclude;
beginInclude = endExclude;
endExclude = tmp;
}
if (beginInclude >= length) {
return (A) Array.newInstance(this.componentType, 0);
}
if (endExclude > length) {
endExclude = length;
}
if (step <= 1) {
step = 1;
}
final int size = (endExclude - beginInclude + step - 1) / step;
final A result = (A) Array.newInstance(this.componentType, size);
int j = 0;
for (int i = beginInclude; i < endExclude; i += step) {
Array.set(result, j, get(i));
j++;
}
return result;
}
/**
* 检查数组是否有序升序或者降序
* <p>若传入空数组则返回{@code false}元素全部相等返回 {@code true}</p>
*
* @param comparator 比较器
* @return 数组是否有序
* @throws NullPointerException 如果数组元素含有null值
* @since 6.0.0
*/
public boolean isSorted(final Comparator<? super A> comparator) {
if (isEmpty()) {
return false;
}
final int lastIndex = this.length - 1;
// 对比第一个和最后一个元素大致预估这个数组是升序还是降序
final int cmp = comparator.compare(get(0), get(lastIndex));
if (cmp < 0) {
return isSorted(comparator, false);
} else if (cmp > 0) {
return isSorted(comparator, true);
}
// 可能全等数组
for (int i = 0; i < lastIndex; i++) {
if (comparator.compare(get(i), get(i + 1)) != 0) {
return false;
}
}
return true;
}
/**
* 数组是否有有序
* <ul>
* <li>反序前一个小于后一个则返回错</li>
* <li>正序前一个大于后一个则返回错</li>
* </ul>
*
* @param comparator {@link Comparator}
* @param isDESC 是否反序
* @return 是否有序
*/
public boolean isSorted(final Comparator<? super A> comparator, final boolean isDESC) {
if (null == comparator) {
return false;
}
int compare;
for (int i = 0; i < this.length; i++) {
compare = comparator.compare(get(i), get(i + 1));
if ((isDESC && compare < 0) ||
(false == isDESC && compare > 0)) {
// 反序前一个小于后一个则返回错
// 正序前一个大于后一个则返回错
return false;
}
}
return true;
}
@Override
public String toString() {
final A array = this.array;

View File

@ -317,7 +317,7 @@ public class CompareUtil {
*/
@SuppressWarnings("unchecked")
public static <T, U> Comparator<T> comparingIndexed(final Function<? super T, ? extends U> keyExtractor, final Iterable<U> objs) {
return comparingIndexed(keyExtractor, false, ArrayUtil.toArray(objs, (Class<U>) objs.iterator().next().getClass()));
return comparingIndexed(keyExtractor, false, ArrayUtil.ofArray(objs, (Class<U>) objs.iterator().next().getClass()));
}
/**

View File

@ -20,6 +20,7 @@ import org.dromara.hutool.core.util.CharsetUtil;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
/**
* {@link ByteBuffer} 工具类<br>
@ -31,6 +32,26 @@ import java.nio.charset.Charset;
*/
public class BufferUtil {
/**
* {@link ByteBuffer} 转byte数组
*
* @param bytebuffer {@link ByteBuffer}
* @return byte数组
*/
public static byte[] toBytes(final ByteBuffer bytebuffer) {
if (bytebuffer.hasArray()) {
return Arrays.copyOfRange(bytebuffer.array(), bytebuffer.position(), bytebuffer.limit());
} else {
final int oldPosition = bytebuffer.position();
bytebuffer.position(0);
final int size = bytebuffer.limit();
final byte[] buffers = new byte[size];
bytebuffer.get(buffers);
bytebuffer.position(oldPosition);
return buffers;
}
}
/**
* 拷贝到一个新的ByteBuffer
*

View File

@ -0,0 +1,41 @@
package org.dromara.hutool.core.array;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class ArrayWrapperTest {
@Test
void getSubTest() {
ArrayWrapper<int[]> array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5});
int[] sub = array.getSub(1, 4);
Assertions.assertArrayEquals(new int[]{2, 3, 4}, sub);
array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5, 6});
sub = array.getSub(1, 4);
Assertions.assertArrayEquals(new int[]{2, 3, 4}, sub);
}
@Test
void getSubStepTest() {
ArrayWrapper<int[]> array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5});
int[] sub = array.getSub(1, 4, 2);
Assertions.assertArrayEquals(new int[]{2, 4}, sub);
array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5, 6});
sub = array.getSub(1, 4, 2);
Assertions.assertArrayEquals(new int[]{2, 4}, sub);
array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5, 6});
sub = array.getSub(0, 5, 2);
Assertions.assertArrayEquals(new int[]{1, 3, 5}, sub);
array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5, 6});
sub = array.getSub(0, 5, 3);
Assertions.assertArrayEquals(new int[]{1, 4}, sub);
array = ArrayWrapper.of(new int[]{1, 2, 3, 4, 5, 6});
sub = array.getSub(1, 6, 2);
Assertions.assertArrayEquals(new int[]{2, 4, 6}, sub);
}
}

View File

@ -305,7 +305,7 @@ public class ArrayUtilTest {
@Test
public void toArrayTest() {
final List<String> list = ListUtil.of("A", "B", "C", "D");
final String[] array = ArrayUtil.toArray(list, String.class);
final String[] array = ArrayUtil.ofArray(list, String.class);
Assertions.assertEquals("A", array[0]);
Assertions.assertEquals("B", array[1]);
Assertions.assertEquals("C", array[2]);