org.neo4j.internal.helpers.ArrayUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-common Show documentation
Show all versions of neo4j-common Show documentation
Non-domain infrastructure code that is common to many Neo4j components.
The newest version!
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.internal.helpers;
import static java.util.Arrays.copyOf;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* Methods "missing" from {@link Arrays} are provided here.
*
*/
public final class ArrayUtil {
public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Count missing items in an array.
* The order of items doesn't matter.
*
* @param array Array to examine
* @param contains Items to look for
* @param The type of the array items
* @return how many of the items in {@code contains} are missing from {@code array}.
*/
public static int missing(T[] array, T[] contains) {
int missing = 0;
for (T check : contains) {
if (!contains(array, check)) {
missing++;
}
}
return missing;
}
/**
* Count items from a different array contained in an array.
* The order of items doesn't matter.
*
* @param array Array to examine
* @param contains Items to look for
* @param The type of the array items
* @return {@code true} if all items in {@code contains} exists in {@code array}, otherwise {@code false}.
*/
public static boolean containsAll(T[] array, T[] contains) {
for (T check : contains) {
if (!contains(array, check)) {
return false;
}
}
return true;
}
/**
* Check if array contains item.
*
* @param array Array to examine
* @param contains Single item to look for
* @param The type of the array items
* @return {@code true} if {@code contains} exists in {@code array}, otherwise {@code false}.
*/
public static boolean contains(T[] array, T contains) {
return contains(array, array.length, contains);
}
/**
* Check if array contains item.
*
* @param array Array to examine
* @param arrayLength Number of items to check, from the start of the array
* @param contains Single item to look for
* @param The type of the array items
* @return {@code true} if {@code contains} exists in {@code array}, otherwise {@code false}.
*/
public static boolean contains(T[] array, int arrayLength, T contains) {
for (int i = 0; i < arrayLength; i++) {
T item = array[i];
if (nullSafeEquals(item, contains)) {
return true;
}
}
return false;
}
/**
* Compare two items for equality; if both are {@code null} they are regarded as equal.
*
* @param first First item to compare
* @param other Other item to compare
* @param The type of the items
* @return {@code true} if {@code first} and {@code other} are both {@code null} or are both equal.
*/
public static boolean nullSafeEquals(T first, T other) {
return first == null ? first == other : first.equals(other);
}
/**
* Get the union of two arrays.
* The resulting array will not contain any duplicates.
*
* @param first First array
* @param other Other array
* @param The type of the arrays
* @return an array containing the union of {@code first} and {@code other}. Items occurring in
* both {@code first} and {@code other} will only have of the two in the resulting union.
*/
public static T[] union(T[] first, T[] other) {
if (first == null || other == null) {
return first == null ? other : first;
}
int missing = missing(first, other);
if (missing == 0) {
return first;
}
// An attempt to add the labels as efficiently as possible
T[] union = copyOf(first, first.length + missing);
int cursor = first.length;
for (T candidate : other) {
if (!contains(first, candidate)) {
union[cursor++] = candidate;
missing--;
}
}
assert missing == 0;
return union;
}
/**
* Create an array from a single first item and additional items following it.
*
* @param first the item to put first
* @param additional the additional items to add to the array
* @param the type of the items
* @return a concatenated array where {@code first} as the item at index {@code 0} and the additional
* items following it.
*/
@SafeVarargs
public static T[] concat(T first, T... additional) {
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(additional.getClass().getComponentType(), additional.length + 1);
result[0] = first;
System.arraycopy(additional, 0, result, 1, additional.length);
return result;
}
/**
* Create a array from a existing array and additional items following it.
*
* @param initial the initial array
* @param additional the additional items that would be added into the initial array
* @param the type of the array items
* @return a concatenated array and the additional items following it.
*/
@SafeVarargs
public static T[] concat(T[] initial, T... additional) {
@SuppressWarnings("unchecked")
T[] result =
(T[]) Array.newInstance(additional.getClass().getComponentType(), initial.length + additional.length);
System.arraycopy(initial, 0, result, 0, initial.length);
System.arraycopy(additional, 0, result, initial.length, additional.length);
return result;
}
/**
* Create a single array from many arrays.
*
* @param initial an initial array
* @param additional additional arrays to be concatenated with the initial array
* @param the type of the array items
* @return the concatenated array
*/
@SafeVarargs
public static T[] concatArrays(T[] initial, T[]... additional) {
int length = initial.length;
for (T[] array : additional) {
length += array.length;
}
T[] result = Arrays.copyOf(initial, length);
int offset = initial.length;
for (T[] array : additional) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
/**
* Returns the array version of the vararg argument.
*
* @param varargs the items
* @param the type of the items
* @return the array version of the vararg argument.
*/
@SafeVarargs
public static T[] array(T... varargs) {
return varargs;
}
public static T lastOf(T[] array) {
return array[array.length - 1];
}
public static int indexOf(T[] array, T item) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(item)) {
return i;
}
}
return -1;
}
@SafeVarargs
public static T[] without(T[] source, T... toRemove) {
T[] result = Arrays.copyOf(source, source.length);
int length = result.length;
for (T candidate : toRemove) {
int index = indexOf(result, candidate);
if (index != -1) {
if (index + 1 < length) { // not the last one
result[index] = result[length - 1];
}
length--;
}
}
return length == result.length ? result : Arrays.copyOf(result, length);
}
public static void reverse(T[] array) {
for (int low = 0, high = array.length - 1; high - low > 0; low++, high--) {
T lowItem = array[low];
array[low] = array[high];
array[high] = lowItem;
}
}
public static T single(T[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("Expected an array with one element, but the array was empty: "
+ array.getClass().getSimpleName());
}
if (array.length > 1) {
throw new IllegalArgumentException("Expected an array with one element, but the array had " + array.length
+ " elements: " + Arrays.toString(array));
}
return array[0];
}
private ArrayUtil() { // No instances allowed
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy