hytale-server/com/hypixel/hytale/builtin/hytalegenerator/ArrayUtil.java

145 lines
4.2 KiB
Java

package com.hypixel.hytale.builtin.hytalegenerator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import javax.annotation.Nonnull;
public class ArrayUtil {
@Nonnull
public static <T> T[] brokenCopyOf(@Nonnull T[] a) {
T[] copy = (T[])(new Object[a.length]);
System.arraycopy(a, 0, copy, 0, a.length);
return copy;
}
public static <T> void copy(@Nonnull T[] source, @Nonnull T[] destination) {
if (source.length != destination.length) {
throw new IllegalArgumentException("arrays must have the same size");
} else {
System.arraycopy(source, 0, destination, 0, source.length);
}
}
@Nonnull
public static <T> T[] append(@Nonnull T[] a, T e) {
T[] expanded = (T[])(new Object[a.length + 1]);
System.arraycopy(a, 0, expanded, 0, a.length);
expanded[a.length] = e;
return expanded;
}
@Nonnull
public static <T> List<List<T>> split(@Nonnull List<T> list, int partCount) {
if (partCount < 1) {
throw new IllegalArgumentException("parts must be greater than 0");
} else if (partCount == 1) {
return Collections.singletonList(list);
} else {
List<List<T>> out = new ArrayList<>(partCount);
int listSize = list.size();
if (listSize <= partCount) {
for (int i = 0; i < listSize; i++) {
out.add(List.of(list.get(i)));
}
for (int i = listSize; i < partCount; i++) {
out.add(List.of());
}
return out;
} else {
int[] partSizes = getPartSizes(listSize, partCount);
int elementIndex = 0;
for (int partIndex = 0; partIndex < partCount; partIndex++) {
int partSize = partSizes[partIndex];
List<T> partList = new ArrayList<>(partSize);
for (int i = 0; i < partSize; i++) {
partList.add(list.get(elementIndex++));
}
out.add(partList);
}
return out;
}
}
}
public static int[] getPartSizes(int total, int partCount) {
if (total >= 0 && partCount >= 1) {
if (total == 0) {
return new int[]{total};
} else {
int[] sizes = new int[partCount];
int baseSize = total / partCount;
int remainder = total % partCount;
for (int i = 0; i < partCount; i++) {
if (i < remainder) {
sizes[i] = baseSize + 1;
} else {
sizes[i] = baseSize;
}
}
return sizes;
}
} else {
throw new IllegalArgumentException("total and/or parts must be greater than 0");
}
}
public static <T, G> int sortedSearch(@Nonnull List<T> sortedList, @Nonnull G gauge, @Nonnull BiFunction<G, T, Integer> comparator) {
int BINARY_SIZE_THRESHOLD = 250;
if (sortedList.isEmpty()) {
return -1;
} else if (sortedList.size() == 1) {
return comparator.apply(gauge, sortedList.getFirst()) == 0 ? 0 : -1;
} else if (sortedList.size() <= 250) {
for (int i = 0; i < sortedList.size(); i++) {
if (comparator.apply(gauge, sortedList.get(i)) == 0) {
return i;
}
}
return -1;
} else {
return binarySearch(sortedList, gauge, comparator);
}
}
public static <T, G> int binarySearch(@Nonnull List<T> sortedList, @Nonnull G gauge, @Nonnull BiFunction<G, T, Integer> comparator) {
if (sortedList.isEmpty()) {
return -1;
} else {
int min = 0;
int max = sortedList.size();
while (true) {
int index = (max + min) / 2;
T item = sortedList.get(index);
int comparison = comparator.apply(gauge, item);
if (comparison == 0) {
return index;
}
if (min == max - 1) {
return -1;
}
if (comparison == -1) {
max = index;
}
if (comparison == 1) {
min = index;
}
}
}
}
}