All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.deephaven.tuple.ArrayTuple Maven / Gradle / Ivy

There is a newer version: 0.36.1
Show newest version
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.tuple;

import io.deephaven.tuple.serialization.SerializationUtils;
import io.deephaven.tuple.serialization.StreamingExternalizable;
import gnu.trove.map.TIntObjectMap;
import io.deephaven.util.compare.ObjectComparisons;
import io.deephaven.util.type.ArrayTypeUtils;
import org.jetbrains.annotations.NotNull;

import java.io.*;
import java.util.Arrays;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

/**
 * 

* N-Tuple key class backed by an array of elements. */ public class ArrayTuple implements Comparable, Externalizable, StreamingExternalizable, CanonicalizableTuple { private static final long serialVersionUID = 1L; private Object[] elements; private transient int cachedHashCode; /** * Construct a tuple backed by the supplied array of elements. The elements array should not be changed after this * call. * * @param elements The array to wrap */ public ArrayTuple(final Object... elements) { initialize(elements == null ? ArrayTypeUtils.EMPTY_OBJECT_ARRAY : elements); } /** * This is required for {@link Externalizable} support, but should not be used otherwise. */ public ArrayTuple() {} private void initialize(@NotNull final Object[] elements) { this.elements = elements; cachedHashCode = Arrays.hashCode(elements); } @SuppressWarnings("unused") public final T getElement(final int elementIndex) { // noinspection unchecked return (T) elements[elementIndex]; } /** * Return a new array of the elements of this tuple, safe for any use. * * @return A new array of the elements of this tuple */ public final Object[] getElements() { final Object[] exportedElements = new Object[elements.length]; System.arraycopy(elements, 0, exportedElements, 0, elements.length); return exportedElements; } /** * Get the elements of this tuple as a {@link Stream}. * * @return A new {@link Stream} of the elements of this tuple */ public Stream elementStream() { return Arrays.stream(elements); } @Override public final int hashCode() { return cachedHashCode; } @Override public final boolean equals(final Object other) { if (this == other) { return true; } if (other == null || getClass() != other.getClass()) { return false; } final ArrayTuple typedOther = (ArrayTuple) other; return Arrays.equals(elements, typedOther.elements); } @Override public final int compareTo(@NotNull final ArrayTuple other) { if (this == other) { return 0; } final int thisLength = elements.length; if (thisLength != other.elements.length) { throw new IllegalArgumentException("Mismatched lengths in " + ArrayTuple.class.getSimpleName() + " comparison (this.elements=" + Arrays.toString(elements) + ", other.elements=" + Arrays.toString(other.elements) + ')'); } for (int ei = 0; ei < thisLength; ++ei) { final int comparison = ObjectComparisons.compare(elements[ei], other.elements[ei]); if (comparison != 0) { return comparison; } } return 0; } @Override public void writeExternal(@NotNull final ObjectOutput out) throws IOException { out.writeInt(elements.length); for (final Object element : elements) { out.writeObject(element); } } @Override public void readExternal(@NotNull final ObjectInput in) throws IOException, ClassNotFoundException { final int inLength = in.readInt(); final Object[] inElements = new Object[inLength]; for (int ei = 0; ei < inLength; ++ei) { inElements[ei] = in.readObject(); } initialize(inElements); } @Override public void writeExternalStreaming(@NotNull final ObjectOutput out, @NotNull final TIntObjectMap cachedWriters) throws IOException { final int length = elements.length; out.writeInt(length); for (int ei = 0; ei < length; ++ei) { StreamingExternalizable.writeObjectElement(out, cachedWriters, ei, elements[ei]); } } @Override public void readExternalStreaming(@NotNull final ObjectInput in, @NotNull final TIntObjectMap cachedReaders) throws Exception { final int inLength = in.readInt(); final Object[] inElements = new Object[inLength]; for (int ei = 0; ei < inLength; ++ei) { inElements[ei] = StreamingExternalizable.readObjectElement(in, cachedReaders, ei); } initialize(inElements); } @Override public String toString() { return "ArrayTuple{" + Arrays.toString(elements) + '}'; } @Override public ArrayTuple canonicalize(@NotNull final UnaryOperator canonicalizer) { final int thisLength = elements.length; Object[] canonicalElements = null; for (int ei = 0; ei < thisLength; ++ei) { final Object element = elements[ei]; final Object canonicalElement = canonicalizer.apply(element); if (canonicalElements == null && element != canonicalElement) { canonicalElements = new Object[thisLength]; System.arraycopy(elements, 0, canonicalElements, 0, ei); } if (canonicalElements != null) { canonicalElements[ei] = canonicalElement; } } return canonicalElements == null ? this : new ArrayTuple(canonicalElements); } }