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

net.algart.arrays.Array Maven / Gradle / Ivy

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.algart.arrays;

import java.nio.ByteOrder;
import java.util.Objects;

/**
 * 

AlgART array of any elements, read-only access.

* *

It is the basic superinterface for {@link MutableArray} and {@link UpdatableArray}. * Unlike that interfaces, the methods of this interface * does not allow to modify elements or a number of elements. * The instances of this interface, which do not implement * its inheritors {@link UpdatableArray} and {@link MutableArray}, * are usually returned by {@link #asImmutable()} method.

* *

If the elements of this array are primitive values (byte, short, etc.), * the array must implement one of * {@link BitArray}, {@link CharArray}, * {@link ByteArray}, {@link ShortArray}, * {@link IntArray}, {@link LongArray}, * {@link FloatArray}, {@link DoubleArray} * subinterfaces. * In another case, the array must implement {@link ObjectArray} subinterface.

* *

{@link #asImmutable() Immutable} arrays, implementing this interface, * are thread-safe and can be used simultaneously in several threads. * All other kinds of arrays are thread-compatible * and can be synchronized manually if multithreading access is necessary. * Please see more details in the * package description.

* * @author Daniel Alievsky * @see UpdatableArray * @see MutableArray * @see Matrix */ public interface Array { /** * Returns the type of array elements. * For arrays of primitive types, returns:
    *
  • boolean.class for {@link BitArray},
  • *
  • char.class for {@link CharArray},
  • *
  • byte.class for {@link ByteArray},
  • *
  • short.class for {@link ShortArray},
  • *
  • int.class for {@link IntArray}),
  • *
  • long.class for {@link LongArray},
  • *
  • float.class for {@link FloatArray},
  • *
  • double.class for {@link DoubleArray}.
  • *
* All elements of the array are values of this type or (for non-primitive types) * some inheritor of this type. * *

There is a guarantee that this method works very quickly * (usually it just returns a value of some private field). * * @return the type of array elements. * @see Matrix#elementType() * @see Arrays#elementType(Class) */ Class elementType(); /** * Returns the canonical AlgART type of this array: the class of one of 9 basic interfaces, * describing all kinds of AlgART arrays for 8 primitive and any non-primitive element types. * More precisely, returns:

    *
  • {@link BitArray}.class, if this object is an instance of {@link BitArray},
  • *
  • {@link CharArray}.class, if this object is an instance of {@link CharArray},
  • *
  • {@link ByteArray}.class, if this object is an instance of {@link ByteArray},
  • *
  • {@link ShortArray}.class, if this object is an instance of {@link ShortArray},
  • *
  • {@link IntArray}.class, if this object is an instance of {@link IntArray},
  • *
  • {@link LongArray}.class, if this object is an instance of {@link LongArray},
  • *
  • {@link FloatArray}.class, if this object is an instance of {@link FloatArray},
  • *
  • {@link DoubleArray}.class, if this object is an instance of {@link DoubleArray},
  • *
  • {@link ObjectArray}.class, if this object is an instance of {@link ObjectArray}.
  • *
* *

There is a guarantee that this method works very quickly * (usually it just returns a constant value). * * @return canonical AlgART type of this array. */ Class type(); /** * Returns the canonical updatable AlgART type of arrays with the same element types: * the class of one of 9 basic interfaces, * describing all kinds of updatable AlgART arrays for 8 primitive and any non-primitive element types. * More precisely, returns:

    *
  • {@link UpdatableBitArray}.class, if this object is an instance of {@link BitArray},
  • *
  • {@link UpdatableCharArray}.class, if this object is an instance of {@link CharArray},
  • *
  • {@link UpdatableByteArray}.class, if this object is an instance of {@link ByteArray},
  • *
  • {@link UpdatableShortArray}.class, if this object is an instance of {@link ShortArray},
  • *
  • {@link UpdatableIntArray}.class, if this object is an instance of {@link IntArray},
  • *
  • {@link UpdatableLongArray}.class, if this object is an instance of {@link LongArray},
  • *
  • {@link UpdatableFloatArray}.class, if this object is an instance of {@link FloatArray},
  • *
  • {@link UpdatableDoubleArray}.class, if this object is an instance of {@link DoubleArray},
  • *
  • {@link UpdatableObjectArray}.class, if this object is an instance of {@link ObjectArray}.
  • *
* *

There is a guarantee that this method works very quickly * (usually it just returns a constant value). * * @return canonical AlgART type of updatable array of the same kind. */ Class updatableType(); /** * Returns the canonical resizable AlgART type of arrays with the same element types: * the class of one of 9 basic interfaces, * describing all kinds of resizable AlgART arrays for 8 primitive and any non-primitive element types. * More precisely, returns:

    *
  • {@link MutableBitArray}.class, if this object is an instance of {@link BitArray},
  • *
  • {@link MutableCharArray}.class, if this object is an instance of {@link CharArray},
  • *
  • {@link MutableByteArray}.class, if this object is an instance of {@link ByteArray},
  • *
  • {@link MutableShortArray}.class, if this object is an instance of {@link ShortArray},
  • *
  • {@link MutableIntArray}.class, if this object is an instance of {@link IntArray},
  • *
  • {@link MutableLongArray}.class, if this object is an instance of {@link LongArray},
  • *
  • {@link MutableFloatArray}.class, if this object is an instance of {@link FloatArray},
  • *
  • {@link MutableDoubleArray}.class, if this object is an instance of {@link DoubleArray},
  • *
  • {@link MutableObjectArray}.class, if this object is an instance of {@link ObjectArray}.
  • *
* *

There is a guarantee that this method works very quickly * (usually it just returns a constant value). * * @return canonical AlgART class of a resizable array of the same kind. */ Class mutableType(); /** * Returns the length: number of elements in this array. * *

There is a guarantee that this method works very quickly * (usually it just returns a value of some private field). * The result of this method is never negative.

* * @return the length: number of elements in this array. * @see Matrix#size() */ long length(); /** * Returns the length as a 32-bit int value. * If the {@link #length() actual length} is greater than Integer.MAX_VALUE, * throws {@link TooLargeArrayException}. * *

This method is convenient to allocate memory for a regular Java array * if you want to ensure that this AlgART array is not too big to be entirely copied into a Java array.

* * @return the length: number of elements in this array, if it is less than 231. * @throws TooLargeArrayException if the actual length is greater than * Integer.MAX_VALUE=231−1. * @see Matrix#size32() */ default int length32() throws TooLargeArrayException { long result = length(); if (result < 0) { throw new AssertionError("Negative result " + result + " of length() method"); } if (result > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large array (>= 2^31 elements): " + this); } return (int) result; } /** * Equivalent to the call {@link #length() length}() == 0. * * @return true if the array is empty, i.e. its length is zero. * @see Matrix#isEmpty() */ default boolean isEmpty() { return length() == 0; } /** * Returns the capacity of this array: the number of elements * allocated for storing elements in this array. * For resizable arrays (implementing {@link MutableArray} interface), * the internal storage will be reallocated after {@link MutableArray#length(long)} * call only if the new length is greater than the current capacity. * *

There is a guarantee that this method works very quickly * (usually it just returns a value of some private field). * * @return the capacity of this array. */ long capacity(); /** * Returns the element #index. * If this array contains elements of primitive types, * the value is automatically wrapped in an object (Boolean, * Byte, etc.). * *

It is a low-level method. * For arrays of primitive elements, implementing one of corresponding interfaces * {@link BitArray}, {@link CharArray}, * {@link ByteArray}, {@link ShortArray}, * {@link IntArray}, {@link LongArray}, * {@link FloatArray}, {@link DoubleArray}, * we recommend to use more efficient equivalent method of that interfaces: * {@link BitArray#getBit(long)}, {@link CharArray#getChar(long)}, * {@link ByteArray#getByte(long)}, {@link ShortArray#getShort(long)}, * {@link IntArray#getInt(long)}, {@link LongArray#getLong(long)}, * {@link FloatArray#getFloat(long)}, {@link DoubleArray#getDouble(long)}. * For other arrays, implementing {@link ObjectArray}, * we recommend to use {@link ObjectArray#get(long)}. * * @param index index of the element to get. * @return the element at the specified position in this array. * @throws IndexOutOfBoundsException if index is out of range 0..length()-1. */ Object getElement(long index); /** * Copies count elements of this array, starting from arrayPos index, * into the specified Java array of corresponding type, starting from destArrayOffset index. * *

For non-primitive element type ({@link ObjectArray}, {@link UpdatableObjectArray}, * {@link MutableObjectArray} subinterfaces), this method may allocate new instances * for Java array elements destArray[destArrayOffset]..destArray[destArrayOffset+count-1], * but also may change the state of already existing non-null elements: it depends on implementation. * In any case, you can be sure that if some of the target elements destArray[k]==null, * this method always allocate new element. * *

Note: if IndexOutOfBoundsException occurs due to attempt to write data outside the passed * Java array, the target Java array can be partially filled. * In other words, this method can be non-atomic regarding this failure. * All other possible exceptions are checked in the very beginning of this method * before any other actions (the standard way for checking exceptions). * * @param arrayPos starting position in this AlgART array. * @param destArray the target Java array. * @param destArrayOffset starting position in the target Java array. * @param count the number of elements to be copied. * @throws NullPointerException if destArray argument is {@code null}. * @throws IllegalArgumentException if destArray argument is not an array or * if count < 0. * @throws IndexOutOfBoundsException if copying causes access of data outside this array or target Java array. * @throws ArrayStoreException if destArray element type mismatches with this array * {@link #elementType()}. * @throws ClassCastException if destArray element type mismatches with this array * {@link #elementType()} * (both this and ArrayStoreException are possible, * depending on implementation). * @see DirectAccessible * @see UpdatableArray#setData(long, Object, int, int) * @see BitArray#getBits(long, long[], long, long) */ void getData(long arrayPos, Object destArray, int destArrayOffset, int count); /** * Copies min(this.{@link #length() length() - arrayPos}, destArray.length}) * elements of this array, starting from arrayPos index, * into the specified Java array of corresponding type, starting from 0 index. * *

For non-primitive element type ({@link ObjectArray}, {@link UpdatableObjectArray}, * {@link MutableObjectArray} subinterfaces), this method may allocate new instances * for Java array elements destArray[0]..destArray[count-1], * but also may change the state of already existing non-null elements: it depends on implementation. * In any case, you can be sure: if some of the target elements destArray[k]==null, * this method always allocates new elements. * * @param arrayPos starting position in this AlgART array. * @param destArray the target Java array. * @throws NullPointerException if destArray argument is {@code null}. * @throws IllegalArgumentException if destArray argument is not an array. * @throws ArrayStoreException if destArray element type mismatches with this array * {@link #elementType()}. * @throws ClassCastException if destArray element type mismatches with this array * {@link #elementType()} * (both this and ArrayStoreException are possible, * depending on implementation). * @see DirectAccessible * @see #getData(long, Object, int, int) * @see UpdatableArray#setData(long, Object) */ void getData(long arrayPos, Object destArray); /** * Returns usual Java-array (zero-filled) with the specified length * and element type returned by {@link #elementType()} method. * *

This method is equivalent to the following call: * java.lang.reflect.Array.newInstance(elementType(), length). * *

This method can be helpful while using together with * {@link #getData(long, Object, int, int) getData} / * {@link UpdatableArray#setData(long, Object, int, int) setData} methods. * * @param length the length of created Java-array. * @return Java-array with the specified length and the same type of elements. * @throws NegativeArraySizeException if the specified length is negative. */ default Object newJavaArray(int length) { return java.lang.reflect.Array.newInstance(elementType(), length); } /** * Returns a view of the portion of this array between fromIndex, * inclusive, and toIndex, exclusive. *

    *
  • If fromIndex and toIndex are equal, the returned array is empty. *
  • The returned array is backed by this array, so — if this array is not immutable * — any changes of the elements of the returned array are reflected in this array, and vice versa. *
  • The capacity of returned array (returned by {@link #capacity()} method) will be * equal to the its length (returned by {@link #length()}, that is toIndex-fromIndex. *
  • The {@link #elementType() type of elements} of the returned array is the same * as the type of elements of this array.
  • *
  • The returned array is {@link #asImmutable() immutable}, * {@link #asTrustedImmutable() trusted immutable} or * {@link #asCopyOnNextWrite() copy-on-next-write}, if, and only if, * this array is immutable, trusted immutable or copy-on-next-write correspondingly.
  • *
  • If (and only if) this array implements {@link UpdatableArray} interface, * then the returned array also implements it. * If (and only if) this array implements {@link DirectAccessible} interface, * then the returned array also implements it. * The returned array never implements {@link MutableArray} interface; * it is always unresizable.
  • *
* *

Like List.subList method, this method eliminates the need * for explicit range operations. * For example, you may use {@link Arrays#sort(UpdatableArray, ArrayComparator)} * method for sorting a fragment of the array. * *

Unlike List.subList, the semantics of the array returned * by this method is well-defined in any case, even in case of * resizing of the source array. * Namely, if the internal storage of this or returned array is reallocated, * then the returned array will cease to be a view of this array. * The only possible reasons for reallocation are the following: * calling {@link MutableArray#length(long)}, * {@link MutableArray#ensureCapacity(long)} or {@link MutableArray#trim()} methods * for this array, or any modification of this or returned array in a case when * this array is {@link #asCopyOnNextWrite() copy-on-next-write}. * Also, if the length of this array will be reduced, * it can lead to clearing some elements in returned array: * see comments to {@link MutableArray#length(long)} method. * * @param fromIndex low endpoint (inclusive) of the subarray. * @param toIndex high endpoint (exclusive) of the subarray. * @return a view of the specified range within this array. * @throws IndexOutOfBoundsException for illegal fromIndex and toIndex * (fromIndex < 0 || toIndex > {@link #length()} * || fromIndex > toIndex). * @see #subArr(long, long) */ Array subArray(long fromIndex, long toIndex); /** * Equivalent to {@link #subArray(long, long) subArray(position, position + count)}. * The only possible difference is other exception messages. * If position+count>Long.MAX_VALUE (overflow), * an exception message is allowed to be not fully correct * (maximal speed is more important than absolutely correct exception messages for such exotic situations). * * @param position start position (inclusive) of the subarray. * @param count number of elements in the subarray. * @return a view of the specified range within this array. * @throws IndexOutOfBoundsException for illegal position and count * (position < 0 || count < 0 * || position + count > {@link #length()}). * @see #subArray(long, long) */ Array subArr(long position, long count); /** * Returns a {@link DataBuffer data buffer} allowing block access to this array * with the specified {@link DataBuffer.AccessMode access mode} and buffer capacity. * *

If this array does not implement {@link UpdatableArray} interface * (so, it is probably {@link #asImmutable() immutable} or {@link #asTrustedImmutable() * trusted immutable}), the mode argument must be {@link DataBuffer.AccessMode#READ}. * *

The capacity argument must be in range 0..237-1 * for {@link BitArray bit arrays} or 0..231-1 for all other element types. * *

If the capacity argument is greater than this array {@link #length()}, * it is truncated to this length. * * @param mode the access mode for new buffer. * @param capacity the capacity of the buffer. * @return new data buffer for accessing this array. * @throws NullPointerException if mode argument is {@code null}. * @throws IllegalArgumentException if the mode is not the {@link DataBuffer.AccessMode#READ}, * but this arrays does not implement {@link UpdatableArray} interface, * or if the specified capacity is negative or too high * (>=0..237 for bits or >=0..231 for * other element types). * @see #buffer(net.algart.arrays.DataBuffer.AccessMode) * @see #buffer(long) * @see #buffer() */ DataBuffer buffer(DataBuffer.AccessMode mode, long capacity); /** * Equivalent to {@link #buffer(net.algart.arrays.DataBuffer.AccessMode, long) * buffer(mode, someCapacity)}, where mode is the argument of this method * and someCapacity is chosen automatically to provide good performance in typical situations. * Usually, the capacity is chosen to get a buffer occupying several kilobytes * that can fit in an internal cache of most processors. * *

In any case, you can be sure that the chosen capacity will not be greater than * Integer.MAX_VALUE-64. * * @param mode the access mode for new buffer. * @return new data buffer for accessing this array. * @throws NullPointerException if mode argument is {@code null}. * @throws IllegalArgumentException if the mode is not the {@link DataBuffer.AccessMode#READ}, * but this arrays does not implement {@link UpdatableArray} interface. */ DataBuffer buffer(DataBuffer.AccessMode mode); /** * Equivalent to {@link #buffer(net.algart.arrays.DataBuffer.AccessMode, long) * buffer(suitableMode, capacity)}, where capacity is the argument of this method * and suitableMode is chosen automatically. Namely, suitableMode is:

    *
  • {@link DataBuffer.AccessMode#READ_WRITE} if this array implements {@link UpdatableArray} interface * (i.e., is modifiable and, maybe, resizable);
  • *
  • {@link DataBuffer.AccessMode#READ} if this array does not implements this interface * (i.e., probably, immutable or {@link #asTrustedImmutable trusted immutable}).
  • *
* * @param capacity the capacity of the buffer. * @return new data buffer for accessing this array. * @throws IllegalArgumentException if the specified capacity is negative or too high * (>=0..237 for bits or >=0..231 for * other element types). */ DataBuffer buffer(long capacity); /** * Equivalent to {@link #buffer(net.algart.arrays.DataBuffer.AccessMode, long) * buffer(suitableMode, someCapacity)}, where both suitableMode and someCapacity * arguments are chosen automatically. The algorithm of choosing these arguments is the same * as for {@link #buffer(net.algart.arrays.DataBuffer.AccessMode)} and {@link #buffer(long)} methods. * *

In any case, you can be sure that the chosen capacity will not be greater than * Integer.MAX_VALUE-64. * * @return new data buffer for accessing this array. */ DataBuffer buffer(); /** * Returns an immutable view of this array. * If this array is already immutable (i.e. {@link #isImmutable()} is true), * returns a reference to this object. * *

A array is considered to be immutable, * if there are no ways to modify its content or state with help of this instance. * In particular, immutable arrays never * implement {@link UpdatableArray} or {@link DirectAccessible} interfaces. * Moreover, any third-party implementation of Array interface * must return an instance of a class, which has no methods or fields * allowing to change this instance. * *

Query operations on the returned array "read through" * to this array. The returned view is also unresizable * (see {@link UpdatableArray#asUnresizable()}). * *

The returned view (when it is not a reference to this object) contains the same elements * as this array, but independent length, start offset, capacity, copy-on-next-write and * possible other information about array characteristics besides its elements, * as for {@link #shallowClone()} method. * If modifications of the array characteristics lead to reallocation * of the internal storage, then the returned array ceases to be a view of this array. * The only possible reasons for reallocation are the following: * calling {@link MutableArray#length(long)}, * {@link MutableArray#ensureCapacity(long)} or {@link MutableArray#trim()} methods * for this array, or any modification of this or returned array in a case when * this array is {@link #asCopyOnNextWrite() copy-on-next-write}. * *

By default, the array factories ({@link MemoryModel memory models}) create mutable arrays, * but they can be converted to immutable by this method. * *

Note: {@link #isNew()} method, called for the result of this method, always returns false * — because it does not implement {@link UpdatableArray}. * *

Also note: {@link #isNewReadOnlyView()} method, called for the result of this method, always returns * the same value as {@link #isNewReadOnlyView()} for this object. * Really, *

    *
  • it this object is immutable ({@link #isImmutable()}==true), * then it is obvious (this method just returns a reference to this array);
  • *
  • it this object is not immutable ({@link #isImmutable()}==false), * then, according to the contract to {@link #isNewReadOnlyView()} method, * {@link #isNewReadOnlyView()} must return false for this array * (in another case {@link #isImmutable()} would return true) and * it also must return false for the returned array * (because it is a view of another array and not an original view of external data — * see the beginning of the comment to {@link #isNewReadOnlyView()}). *
  • *
* * @return an immutable view of this array (or a reference to this array if it is already immutable). * @see #isImmutable() * @see #asTrustedImmutable() * @see #mutableClone(MemoryModel) * @see #updatableClone(MemoryModel) * @see UpdatableArray#asUnresizable() */ Array asImmutable(); /** * Returns true if this instance is immutable, i.e. there are no ways to * change its content or state. (See {@link #asImmutable()} method for more details.) * *

It is possible that array is immutable in fact, but this method returns false: * for example, if the array is mapped to read-only file. However, it is guaranteed: * if the array was created via {@link #asImmutable} method, this method * returns true. * *

Typically, this method returns true if the array: *

    *
  1. does not implement {@link UpdatableArray} interface;
  2. *
  3. does not implement {@link DirectAccessible} interface, or implements it, * but {@link DirectAccessible#hasJavaArray()} method returns false.
  4. *
* *

But you should not use these conditions to check whether an array is immutable; * please use this method instead. * In principle, it is possible that both these conditions are satisfied, but the array * is though mutable. Maybe, some class from another package (or from future versions * of this package), implementing {@link Array} interface, does not implement * neither {@link UpdatableArray}, nor {@link DirectAccessible}, but offers other methods * allowing to change its state or content. * *

Note: if this method returns true, it does not mean that its content cannot * be modified at all. Quite the contrary, usually an immutable array a * is just an immutable view of another mutable array b * (created via a=b.{@link #asImmutable} call), * and the original array b does allow to change the content of the immutable array a. * Immutability means only that there are no ways to modify the content or state of the object a, * if this object a is the only reference to its content, which you have. * The same note is true for immutable collections, created by the standard * Collections.unmodifiableList and analogous methods. * Please compare this with the behavior of another method {@link #isNewReadOnlyView()}. * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return true if this instance is immutable. * @see #asImmutable() */ boolean isImmutable(); /** * Returns a trusted immutable view of this array. * If this array is already trusted immutable, returns a reference to this object. * *

A array is considered to be "trusted" immutable, * if it potentially can change its elements, * but the Java code working with this array promises that it will not change them. * The returned instance never implements {@link UpdatableArray}, * but may implement {@link DirectAccessible}, that allow quick access to its elements. * As for {@link #asImmutable() usual immutable view}, * query operations on the returned array "read through" * to this array. * *

The only standard way allowing to change elements of the returned array * is using {@link DirectAccessible#javaArray()} method, in a case when the array is backed * by an accessible array. * But the Java code, processing the trusted immutable array, * must use this method only for quick reading elements and not try to change them. * If, despite the promise, the elements of the trusted immutable array are changed, * the {@link UnallowedMutationError} may be thrown by the call of * {@link #checkUnallowedMutation()} method. * *

In some implementations — for example, if {@link DirectAccessible} * interface is not supported by this array * — this method may return the same result as {@link #asImmutable()}. * *

The returned view is always unresizable. * *

The returned view (when it is not a reference to this object) contains the same elements * as this array, but independent length, start offset, capacity, copy-on-next-write and * possible other information about array characteristics besides its elements, * as for {@link #shallowClone()} method. * If modifications of this array characteristics lead to reallocation * of the internal storage, then the returned array ceases to be a view of this array. * The only possible reasons for reallocation are the following: * calling {@link MutableArray#length(long)}, * {@link MutableArray#ensureCapacity(long)} or {@link MutableArray#trim()} methods * for this array, or any modification of this or returned array in a case when * this array is {@link #asCopyOnNextWrite() copy-on-next-write}. * *

Trusted immutable view is a compromise between absolute safety, provided by * {@link #asImmutable() usual immutable view}, and maximal efficiency, * achieved while using the original non-protected array. * Please see the package description * to learn more about possible usage of this method. * * @return a trusted immutable view of this array (or a reference to this array if it is already * trusted immutable). * @see #asImmutable() * @see #checkUnallowedMutation() */ Array asTrustedImmutable(); /** * Tries to check, whether some non-allowed mutations of this {@link #asTrustedImmutable() * trusted immutable} array took place, * and throw {@link UnallowedMutationError} in this case. * Does nothing if this array implement {@link UpdatableArray} interface * or if it is truly immutable. * *

Implementation of this method usually checks whether the hash code was changed since array creation. * *

We recommend to call this method in finally * sections after using the trusted immutable array. * If it is impossible to create necessary finally section, * you may use {@link net.algart.finalizing.Finalizer} class (or an equivalent tool) * to schedule call of this method for the {@link #shallowClone() shallow clone} of this array * on deallocation of this array:

     * Finalizer fin = ...(some global application finalizer);
     * final Array dup = thisArray.shallowClone();
     * // - must be here, not inside the following inner class, to allow deallocation of thisArray
     * fin.invokeOnDeallocation(thisArray, new Runnable() {
     *     void run() {
     *         try {
     *             dup.checkUnallowedMutation();
     *         } catch (UnallowedMutationError ex) {
     *             myLogger.severe(ex.toString());
     *         }
     *     }
     * });
     * 
* Important: while using this finalization scheme, this array must not be * {@link #isCopyOnNextWrite() copy-on-next-write}! * Illegal modifications of copy-on-next-write array will not change * it's shallow clone and will not be detected. * * @throws UnallowedMutationError if some unallowed mutations of this array took place. * @see #asTrustedImmutable() */ void checkUnallowedMutation() throws UnallowedMutationError; /** * Returns a copy-on-next-write view of this array. * If this array is immutable (and only in this case), returns a reference to this object. * If (and only if) this array implements {@link UpdatableArray} interface, * then the returned array also implements it. * If (and only if) this array implements {@link MutableArray} interface, * then the returned array also implements it. * *

Copy-on-next-write array is an array with the following special feature: * the next attempt (but not further!) to modify this array, * or any other access that can lead to its modification (like {@link DirectAccessible#javaArray()} * method), will lead to reallocation of the underlying storage, used for array elements, * before performing the operation. In other words, * you have a guarantee: if this array is a view of some another array or data * (for example, a {@link #subArray(long, long) subarray} or * a {@link SimpleMemoryModel#asUpdatableArray(Object) view of Java array}), * that there are no ways to change that data * via accessing the returned array. Any changes, if they will occur, * will be performed with the newly allocated storage only. * *

Please be careful: if you will want to change arrays created by this method, the result may * be unexpected! For example, an attempt to copy other arrays into "copy-on-next-write" array * by some methods like {@link Arrays#copy(ArrayContext, UpdatableArray, Array)} will probably * do nothing. The reason is working with the array via its subarrays — * for example, {@link Arrays#copy(ArrayContext, UpdatableArray, Array) Arrays.copy} method * splits the source and target arrays into subarrays and copies these subarrays. * (Usual {@link UpdatableArray#copy(Array)} method and other mutation methods * of the resulting array will work normally.) * The main goal of copy-on-next-write arrays is protection against unwanted changing * an original array; it is supposed that the client, in normal situation, will only read * such arrays and will not try to change them. * *

There are no guarantees that the returned array will be a view of this one, * even immediately after creation. * Some implementations of updatable arrays may just return the full (deep) copy of this object, * alike {@link #mutableClone(MemoryModel)} method, and in this case * {@link TooLargeArrayException} is possible. * All implementations from this package, excepting AbstractUpdatableXxxArray classes, * returns a view; * but in AbstractUpdatableXxxArray classes this method is equivalent to * {@link #updatableClone(MemoryModel) updatableClone}({@link Arrays#SMM}). * *

Please note that copy-on-next-write arrays are not traditional copy-on-write objects like * {@link java.util.concurrent.CopyOnWriteArrayList}! In particular, copy-on-next-write arrays * are not thread-safe. * *

The main purpose of using copy-on-next-write arrays is more efficient alternative * to {@link #updatableClone(MemoryModel) cloning} and creating {@link #asImmutable() quite immutable views}, * when we need to be sure that original data will not be corrupted. * Please see the package description * to learn more about possible usage of this technique. * * @return a copy-on-next-write view of this array (or a reference to this array if it is immutable). * @throws TooLargeArrayException if this method actually creates a copy of this array, but * the {@link Array#length() length} of this array is too large * for the memory model, used for allocating a copy. * @see #isCopyOnNextWrite() * @see MemoryModel#newLazyCopy(Array) * @see MemoryModel#newUnresizableLazyCopy(Array) */ Array asCopyOnNextWrite(); /** * Returns true if this array is copy-on-next-write. * In other words, if this method returns true, it means that the next * attempt (but not further) to modify this array, or any other access that can lead to * its modification (like {@link DirectAccessible#javaArray()} method), will lead to * reallocation of the underlying storage. After reallocation, * the array will cease to be copy-on-next-write: further calls of * this method will return false. * *

This method can be useful if it's possible to select another, * more optimal algorithm branch, allowing to avoid reallocation * for copy-on-next-write arrays. The typical example is usage of * {@link DirectAccessible} interface. That interface, providing direct access to * the internal Java array (which is a storage of the array elements), can optimize * most of the algorithms processing an array. However, reallocation of * the Java array, that will be a result of calling {@link DirectAccessible#javaArray()} for * copy-on-next-write array, can make such "optimization" very unwanted. * *

The only standard way to make copy-on-next-write is calling * {@link #asCopyOnNextWrite()} method. * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return true if this array is copy-on-next-write. * @see #asCopyOnNextWrite() */ boolean isCopyOnNextWrite(); /** * Returns true if this instance is unresizable, i.e. there are no ways to * change its length or capacity. * *

It is guaranteed that if the array was created via {@link #asImmutable} method, this method * returns true. * *

Typically, this method returns true if the array does not implement * {@link MutableArray}. * But you should not use this condition to check whether an array is unresizable; * please use this method instead. * Maybe, some class from another package (or from future versions * of this package), implementing this {@link Array} interface, does not implement * {@link MutableArray}, but offer another methods allowing to change its state or content. * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return true if this instance is unresizable. * @see UpdatableArray#asUnresizable() */ boolean isUnresizable(); /** * Returns true if this array instance is new, i.e. it was created * by one of {@link MemoryModel} methods, creating an array or a matrix (newXxx * or valueOf), or by fully equivalent methods. * All other ways of creating AlgART array instance ({@link #asImmutable()}, * {@link #shallowClone()}, {@link #subArray(long, long)}, {@link SimpleMemoryModel#asUpdatableArray(Object)} * etc.) create non-new arrays. * *

In updatable arrays the "new status", returned by this method, can be cleared manually by * {@link UpdatableArray#setNonNew()} method. Note that immutable arrays, not implementing {@link UpdatableArray} * interface, are never new (this method returns false). * *

If the array is new, you can be sure that it is an original object, storing the data, * but not a view of some other array ({@link #asImmutable() immutable view}, * {@link #subArray(long, long) subarray}, etc.) or of another kind of data (Java array, file, etc.) * This can be important for managing data, associated with AlgART arrays. * *

For example, let we have some source (factory), generating AlgART arrays * (like a library of installable Java plugins), and we need to safely store the content * of these arrays in some permanent storage. * Of course, we can store a full clone of each array with help of {@link #updatableClone(MemoryModel)} * or {@link #mutableClone(MemoryModel)} method, but it can be inefficient for very large arrays (many gigabytes). * On the other hand, we usually cannot just store a reference to an AlgART array * or to its internal data: it is very possible, that one array, received from the factory, is a view of another * one ({@link #asImmutable() immutable view}, {@link #subArray(long, long) subarray}, etc.), and storing * both references in our storage will lead to incorrect behavior — possible future changing * of one element of the storage will be reflected in other elements. * *

New status of the array, provided by this method, allows to correctly resolve this problem. * We should store in the storage the full content (clone) of an array, if this method returns false, * or the reference to an array or to its internal data (as {@link DirectAccessible#javaArray()}), * if it returns true. In the second case, we must additionally clear the status of the original * array object, received from the factory, by {@link UpdatableArray#setNonNew()} method — * it guarantees that we shall store only 1 reference to each really new array. * *

Additional important feature, provided by this method: if you know the memory model, which has created this * instance, then you can be absolutely sure in all details of the algorithm of internal storing * the array data (if it is documented in the corresponding memory model). It is important, * for example, for {@link LargeMemoryModel}: if this method returns true, then the content * of this array corresponds to the content of an external file according to a known, fully documented scheme. * Unlike this, another forms of AlgART arrays — like {@link #subArray(long, long) subarrays} — * have no documented correspondence with the content of external data, even when we can retrieve * some information about such data (as a name of the disk file {@link LargeMemoryModel#getDataFilePath(Array)}). * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return whether this array instance is new: a new object, allocated by some {@link MemoryModel}. * @see #isNewReadOnlyView() */ boolean isNew(); /** * Returns true if this array instance is new-read-only-view, i.e. * a newly created view of some external data, providing read-only access to this data — * like {@link LargeMemoryModel#asArray(Object, Class, long, long, java.nio.ByteOrder)} method. * All other ways of creating AlgART array instance (methods of {@link MemoryModel} class, * {@link #asImmutable()}, {@link #shallowClone()}, {@link #subArray(long, long)}} * etc.) create arrays, in which this method returns false. * In the current version of this package, the only ways to create new-read-only-view AlgART array * are the following: *

    *
  • the method * {@link LargeMemoryModel#asArray(Object, Class, long filePosition, long fileAreaSize, ByteOrder byteOrder)}, * when its filePosition argument is zero (filePosition==0); *
  • *
  • the versions of this method for concrete element types * {@link LargeMemoryModel#asBitArray(Object, long, long, java.nio.ByteOrder) asBitArray}, * {@link LargeMemoryModel#asCharArray(Object, long, long, java.nio.ByteOrder) asCharArray}, * {@link LargeMemoryModel#asByteArray(Object, long, long, java.nio.ByteOrder) asByteArray}, * {@link LargeMemoryModel#asShortArray(Object, long, long, java.nio.ByteOrder) asShortArray}, * {@link LargeMemoryModel#asIntArray(Object, long, long, java.nio.ByteOrder) asIntArray}, * {@link LargeMemoryModel#asLongArray(Object, long, long, java.nio.ByteOrder) asLongArray}, * {@link LargeMemoryModel#asFloatArray(Object, long, long, java.nio.ByteOrder) asFloatArray}, * {@link LargeMemoryModel#asDoubleArray(Object, long, long, java.nio.ByteOrder) asDoubleArray} * in a case of the same condition: their filePosition argument is zero; *
  • *
  • {@link LargeMemoryModel#asMatrix(Object filePath, MatrixInfo matrixInfo)} method * in a case when the {@link MatrixInfo#dataOffset() data offset}, stored in its {@link MatrixInfo} argument, * is zero — then the array, extracted from such a matrix by * {@link LargeMemoryModel#getRawArrayForSavingInFile(Matrix)} method, will be * new-read-only-view.
  • *
* *

New-read-only-view status, returned by this method, * is final and cannot be changed after instantiation of the instance. * (More precisely, there are no methods, allowing to change it after finishing * the method, which has created a new array instance.) * Note that in updatable arrays, implementing {@link UpdatableArray} * interface, this method returns false always. * Moreover, if this method returns true, then there is a guarantee that * {@link #isImmutable()} method also returns true. * *

If this method returns true, you can be sure that it is an original object, * associated with external data with read-only access rights, * but not a view of some other array ({@link #asImmutable() immutable view}, * {@link #subArray(long, long) subarray}, etc.) and not an updatable view of some external data, * allowing to change them. * This can improve efficiency of managing data, associated with AlgART arrays, in addition to * {@link #isNew()} method. * *

Please read again the possible scheme of storing array data in some storage, listed in the comments * to {@link #isNew()}. Sometimes we need to store some number of absolutely identical AlgART * arrays, corresponding to the same data, maybe very large (many gigabytes). * The listed scheme permits storing only 1 reference to each array * (or its data), because we should avoid the ability of changes in one stored array, * reflecting in another stored array. It is a good and safe strategy, but it does not provide * maximal performance in a case, when we know that all data are immutable (read-only) and we shall never * change them. In the last case, there is no problem to create any number of references to the same * data, as well as there is no problem to create a lot of references to the same * immutable Java object like String. * *

This method allows improving the described behavior. Namely, if this method returns true, * you still may store the reference to an AlgART array or to its internal data in your storage, * though {@link #isNew()} returns false. * Yes, you can so create several references to the same array data, * but it does not lead to incorrect behavior — this data will always remain unchanged. * *

But here is an important warning: while using this technique, you should never try * to increase the access rights to the external data, corresponding to the AlgART array, stored in your storage. * More precisely, you should not try to provide write access to this data — even if the API allows * to do this. In a case of {@link LargeMemoryModel}, it means that you should not access to the disk file, * retrieved from an array by {@link LargeMemoryModel#getDataFilePath(Array)} method, * via {@link LargeMemoryModel#asUpdatableArray(Object, Class, long, long, boolean, java.nio.ByteOrder) * LargeMemoryModel.asUpdatableArray} method — please use the original reference * to AlgART array (where this method returns true) or new instances, * created by {@link LargeMemoryModel#asArray(Object, Class, long, long, java.nio.ByteOrder) * LargeMemoryModel.asArray} method. * Maybe, future versions of {@link LargeMemoryModel} class will contain API, * which will allow to provide OS-level protection against any attempts to write into files, * containing the data, stored in your storage of AlgART arrays. * *

In addition, this method provides the same feature as {@link #isNew()} method: * if you know the memory model, which has created this instance, * then you can be sure in all details of the algorithm of internal storing * the array data (if it is documented in the corresponding memory model). It is important * for {@link LargeMemoryModel}: if this method returns true, then the content * of this array corresponds to the content of an external file according to a known, fully documented scheme. * Unlike this, other forms of AlgART arrays — like {@link #subArray(long, long) subarrays} — * have no documented correspondence with the content of an external data, even when we can retrieve * some information about such data (as a name of the disk file {@link LargeMemoryModel#getDataFilePath(Array)}). * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return whether this array instance is a newly created view of some * external data, providing read-only access to this data. */ boolean isNewReadOnlyView(); /** * Returns true if this array instance is lazy, i.e. * if access to its element means some calculations for producing result or actual saving element. * Examples of lazy arrays are results of * {@link Arrays#asFuncArray(net.algart.math.functions.Func, Class, PArray...)} * and analogous methods. * *

If this method returns false, it means that reading elements * (and writing for {@link UpdatableArray updatable arrays}) is performed as quickly as possible: * it is just copying data from one memory (maybe a disk) to another. * In particular, this method returns false for {@link #isNew new} arrays, * their {@link #asImmutable() immutable views}, {@link #subArray(long, long) subarrays}, etc. * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return whether this array instance if lazy. */ boolean isLazy(); /** * Returns the byte order used by this array for storing data. * *

This value is not important for using AlgART arrays. * The only case when it can be interesting is when the array is stored in some external resources, * for example, in a disk file. * *

For all array instances created by this package the byte order is native * (ByteOrder.nativeOrder()), with the only exception: * arrays, created by {@link LargeMemoryModel#asArray(Object, Class, long, long, ByteOrder)}, * {@link LargeMemoryModel#asUpdatableArray(Object, Class, long, long, boolean, ByteOrder)} methods * and their versions for concrete element types, will have byte order * specified by the argument of these methods. * *

Please note: in the combined arrays, created via {@link CombinedMemoryModel}, * this method returns ByteOrder.nativeOrder(), though the byte order in the * underlying storage arrays may be another. * *

This method never returns {@code null}. * *

There is a guarantee that this method works very quickly * (usually it just returns a constant or a value of some private field). * * @return the byte order used by this array for storing data. */ ByteOrder byteOrder(); /** * Returns a "shallow" clone of this object: * another array consisting of the same elements, * but with independent length, start offset, capacity, copy-on-next-write and * possible other information about any array characteristics besides its elements. * In other words, any changes in the elements of the returned array * are usually reflected in this array, and vice versa; but changes of any other * characteristics of the original or returned array, including the length, * capacity, etc., will not be reflected in another array. * *

Please note: this method never returns a reference to this object, * even if this array is immutable! * Moreover, the returned object does not store any references to this instance in any internal fields. * It can be important while using weak references and reference queues: * this object and its shallow copy are deallocated by the garbage collector separately. * *

There are no guarantees that the returned array will share the elements with this one. * Some implementations may return the full (deep) copy of this object, alike * {@link #updatableClone(MemoryModel)} or {@link #mutableClone(MemoryModel)} methods. * All implementations from this package return a shallow (non-deep) copy. * *

If modifications of this or returned array characteristics lead to reallocation * of the internal storage, then the returned array ceases to be a view of this array. * The only possible reasons for reallocation are the following: * calling {@link MutableArray#length(long)}, * {@link MutableArray#ensureCapacity(long)} or {@link MutableArray#trim()} methods * for this array, or any modification of this or returned array in a case when * this array is {@link #asCopyOnNextWrite() copy-on-next-write}. * *

The values of {@link #length()}, {@link #capacity()}, {@link DirectAccessible#javaArrayOffset()}, * {@link #isCopyOnNextWrite()} in the result will be the same as in this array. * The returned instance implements the same set of interfaces as this array. * *

This method is an analog of the standard Java NIO * {@link java.nio.ByteBuffer#duplicate()} method. However, unlike ByteBuffer.duplicate(), * this method is necessary very rarely. Usually, you need another forms * of array views: {@link #asImmutable()}, {@link UpdatableArray#asUnresizable()}, etc. * The most often usage of this method is finalization * via {@link net.algart.finalizing.Finalizer Finalizer} class: * see example in comments to {@link #checkUnallowedMutation()} method. Also, this method * can be useful if you need to pass an array with the same content * into some another class, but must be sure that further resizing * of the source array will not affect to correct work of that class. * * @return a shallow copy of this object. * @see #length() * @see #capacity() * @see DirectAccessible#javaArrayOffset() * @see #isCopyOnNextWrite() */ Array shallowClone(); /** * Returns a mutable resizable copy of this array. This method is equivalent to the following code: * *

     * memoryModel.{@link MemoryModel#newArray(Array)
     * newArray}(thisArray).{@link UpdatableArray#copy(Array) copy}(thisArray);
     * 
* *

Please note: this method is a good choice for cloning little arrays (thousands, * maybe millions elements). If you clone large arrays by this method, * the user, in particular, has no ways to view the progress of copying or to interrupt copying. * To clone large arrays, we recommend the following code: * *

     * MutableArray clone = memoryModel.{@link MemoryModel#newArray(Array)
     * newArray}(thisArray);
     * {@link Arrays#copy(ArrayContext, UpdatableArray, Array) Arrays.copy}(someContext, clone, a);
     * 
* * @param memoryModel the memory model, used for allocation a new copy of this array. * @return a mutable copy of this array. * @throws NullPointerException if the argument is {@code null}. * @throws UnsupportedElementTypeException if thisArray.{@link Array#elementType()} is not supported * by the specified memory model. * @throws TooLargeArrayException if the {@link Array#length() length} of this array is too large * for this the specified memory model. * @see #updatableClone(MemoryModel) */ MutableArray mutableClone(MemoryModel memoryModel); /** * Returns an unresizable updatable copy of this array. * This method is equivalent to the following code: * *
     * memoryModel.{@link MemoryModel#newUnresizableArray(Array)
     * newUnresizableArray}(thisArray).{@link UpdatableArray#copy(Array) copy}(thisArray);
     * 
* *

Please note: this method is a good choice for cloning little arrays (thousands, * maybe million elements). If you clone large arrays by this method, * the user, in particular, has no ways to view the progress of copying or to interrupt copying. * To clone large arrays, we recommend the following code: * *

     * UpdatableArray clone = memoryModel.{@link MemoryModel#newUnresizableArray(Array)
     * newUnresizableArray}(thisArray);
     * {@link Arrays#copy(ArrayContext, UpdatableArray, Array) Arrays.copy}(someContext, clone, a);
     * 
* * @param memoryModel the memory model, used for allocation a new copy of this array. * @return an updatable copy of this array. * @throws NullPointerException if the argument is {@code null}. * @throws UnsupportedElementTypeException if thisArray.{@link Array#elementType()} is not supported * by the specified memory model. * @throws TooLargeArrayException if the {@link Array#length() length} of this array is too large * for this the specified memory model. * @see #mutableClone(MemoryModel) */ UpdatableArray updatableClone(MemoryModel memoryModel); /** * Returns the Java array containing all the elements in this AlgART array in a proper sequence. * The same data can be retrieved using {@link BitArray#getData(long, Object)} method * with zero arrayPos argument. * If the length of this array is greater than Integer.MAX_VALUE, * this method throws {@link TooLargeArrayException}. * *

The result is always a newly created Java array. * Its length will be equal to current * array.{@link Array#length() length()}, and array elements will be stored * in elements #0..#{@link Array#length() length()}-1} of the returned array. * *

This method always allocates a new Java array. * Thus, the caller is free to modify the returned array. * *

The type of returned array is always one of the following:

    *
  • boolean[] for {@link BitArray}, *
  • char[] for {@link CharArray}, *
  • byte[] for {@link ByteArray}, *
  • short[] for {@link ShortArray}, *
  • int[] for {@link IntArray}, *
  • long[] for {@link LongArray}, *
  • float[] for {@link FloatArray}, *
  • double[] for {@link DoubleArray}, *
  • type[], where type is the result of {@link Array#elementType()} method, * in all other cases. *
* *

Reverse operation — conversion of a Java array into AlgART array — * can be performed by {@link SimpleMemoryModel#asUpdatableArray(Object)} method, * returning a view of Java array, or by {@link MemoryModel#valueOf(Object)} method * of any memory model instance, which actually copies data into a newly allocated array. * * @return Java array containing all the elements in this array. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #ja() * @see #getData(long, Object) * @see PArray#toBoolean() * @see PArray#toByte() * @see PArray#toChar() * @see PArray#toShort() * @see PArray#toInt() * @see PArray#toLong() * @see PArray#toFloat() * @see PArray#toDouble() * @see BitArray#toBit() * @see Matrix#toJavaArray() */ default Object toJavaArray() { final long len = length(); if (len != (int) len) { throw new TooLargeArrayException("Cannot convert AlgART array to Java array, " + "because it is too large: " + this); } Object result = newJavaArray((int) len); getData(0, result); return result; } /** * Returns a reference to the underlying Java array ja, if this AlgART array is its wrapper * (see {@link #isJavaArrayWrapper()}); otherwise equivalent to {@link #toJavaArray()} method. * *

In other words, this method returns a Java-array, absolutely identical to this AlgART array — * having identical length and elements, — and does this as quickly as possible * (unlike {@link #toJavaArray()}, which always copies the data).

* *

This method is equivalent to the following operators:

*
     *     thisArray DirectAccessible da &&
     *                 da.hasJavaArray() &&
     *                 da.javaArrayOffset() == 0 &&
     *                 java.lang.reflect.Array.getLength(da.javaArray()) == thisObject.{@link Array#length()
     *                 length()} ?
     *                 da.javaArray() :
     *                 thisArray.toJavaArray();
     * 
*

but works little faster if the first case, "da.javaArray()", * is selected (this is a wrapper).

* *

There are overridden versions of this method in subinterfaces for specific element types: * {@link BitArray#ja()}, {@link CharArray#ja()}}, * {@link ByteArray#ja()}}, {@link ShortArray#ja()}}, * {@link IntArray#ja()}}, {@link LongArray#ja()}}, * {@link FloatArray#ja()}}, {@link DoubleArray#ja()}}, * {@link ObjectArray#ja()}}.

* *

Be careful: this method can potentially lead to bugs while inaccurate usage. * The typical purpose of this method is to quickly access array data for reading. * But it also allows you to modify this data, * and the results of such modification can be different: this may change the original AlgART array, * but may also not change. (Of course, this is impossible for {@link #isImmutable() immutable} arrays.)

* *

Therefore, if you only need to read the array data, * you should not attempt to modify the Java array * returned by this method: this will help to avoid difficult bugs.

* *

If you really want to modify array data, you may do this by updating the returned Java array, but * you must follow two conditions: * 1) this object must be an instance {@link UpdatableArray} of its subinterfaces; * 2) {@link #isJavaArrayWrapper()} method must return true.

* *

Note that usually you should prefer methods of {@link DirectAccessible} interface * instead of this method, because that interface allows quickly processing subarrays * with non-zero start offsets and mutable arrays, for which the length of underlying Java array (capacity) * is usually greater than the actual AlgART array {@link #length() length}. * But if you are sure that your array is created by {@link SimpleMemoryModel} and is not a subarray, * this method provides the simplest way to receive an identical Java array maximally quickly. * * @return Java array, equivalent to this AlgART array. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see DirectAccessible * @see #isJavaArrayWrapper() * @see #toJavaArray() * @see PArray#jaByte() * @see PArray#jaChar() * @see PArray#jaShort() * @see PArray#jaInt() * @see PArray#jaLong() * @see PArray#jaFloat() * @see PArray#jaDouble() * @see BitArray#jaBit() * @see Matrix#ja() */ Object ja(); /** * Returns true this array is actually a wrapper for * a standard Java array, like wrappers returned by {@link SimpleMemoryModel#asUpdatableArray(Object)} method. * That array is returned by {@link #ja()} method, * if and only if this method returns true; * otherwise {@link #ja()} method returns a copy of array data. * *

More precisely, this method returns true, * if and only if all the following conditions are fulfilled:

*
    *
  1. thisArray instanceof {@link DirectAccessible}; * let da = (DirectAccessible) thisArray;
  2. *
  3. da.{@link DirectAccessible#hasJavaArray() hasJavaArray()};
  4. *
  5. da.{@link DirectAccessible#javaArrayOffset() javaArrayOffset()} == 0;
  6. *
  7. array.{@link Array#length() length()} == n, where n * is the length of Java array * da.{@link DirectAccessible#javaArray() javaArray()}:
    * array.{@link Array#length() length()} == java.lang.reflect.Array.getLength(da.javaArray()) * (this condition is usually not fulfilled, for example, in a growing {@link MutableArray}).
  8. *
* *

In this situation, the specified AlgART array is called a wrapper * of the underlying Java array, returned by da.{@link DirectAccessible#javaArray() javaArray()} * or by {@link #ja()} method.

* * @return whether this array is a wrapper for standard Java array: direct-accessible array with zero offset and * with length, equal to the number of elements in the underlying Java array. * @see #ja() */ default boolean isJavaArrayWrapper() { return this instanceof DirectAccessible da && da.hasJavaArray() && da.javaArrayOffset() == 0 && java.lang.reflect.Array.getLength(da.javaArray()) == length(); } /** * Equivalent to {@link Matrices#matrix(Array, long[]) matrix}(thisArray, dim). * * @param dim the matrix dimensions. * @return new matrix backed by array with the given dimensions. * @throws NullPointerException if array or dim argument is {@code null}. * @throws IllegalArgumentException if the passed array is resizable * (for example, implements {@link MutableArray}), * or if the number of dimensions is 0 (empty dim Java array), * or if some dimensions are negative. * @throws SizeMismatchException if the product of all dimensions is not equal to the array length. * @throws TooLargeArrayException if the product of all dimensions is greater than Long.MAX_VALUE. */ default Matrix matrix(long... dim) { return Matrices.matrix(this, dim); } /** * Equivalent to {@link #loadResources(ArrayContext) loadResources}(null). * This is the most typical case of loading resources. * * @see #loadResources(ArrayContext) * @see #freeResources(ArrayContext) */ default void loadResources() { loadResources(null); } /** * If there are some external resources, associated with this array, — * files, streams, sockets, locks, etc. — * this method makes an effort to ensure that, when it returns, * the content of this array will be resident in physical memory. * In other words, this method tries to preload the content of this array into RAM * to provide the fastest access to its elements in the nearest future. * *

There are no any guarantees that all elements of this array will be really preloaded into RAM. * This method usually avoids loading too large amount of data, comparable with the whole amount of RAM. * For example, if the size of this array is 10 GB, it is possible only first several megabytes * or tens of megabytes will be preloaded. * If you work with a large array, we recommend to call this method * for a not too large its {@link #subArray subarray}, which really should be processed now, for example: * *

     * final int blockSize = 1048576;
     * for (long pos = 0, n = array.{@link #length() length()}; pos < n; pos += blockSize) {
     *     int len = (int)Math.min(blockSize, n - pos);
     *     Array region = array.{@link #subArr subArr}(pos, len);
     *     region.loadResources(someContext)};
     *     // some algorithm processing len elements of this region
     * }
     * 
* *

If the resources, associated with this array, are shared with some another arrays * (usually when one array is a view of another one), this method * tries to preload the content of that arrays, though it is not guaranteed. * This method usually does nothing if the {@link #length() length} of this array is zero. * *

The context argument is necessary to allow user to interrupt this method and to view * the execution progress. Namely, if this argument is not {@code null}, this method probably calls * context.{@link ArrayContext#checkInterruption() checkInterruption} and * context.{@link ArrayContext#updateProgress updateProgress} methods from time to time. * It may be useful if preloading data can require long time, for example, the content should be * loaded from Internet. * You always may pass {@code null} as this argument; then all will work correctly, * but, maybe, the user will be bored for some time. * For all arrays, created by this package, this method works quickly enough * and doesn't require non-null context. * *

This method does nothing for arrays created by the {@link SimpleMemoryModel simple memory model} * and the {@link BufferMemoryModel buffer memory model}, and also for constant arrays * created by {@link Arrays#nByteCopies}, {@link Arrays#nCharCopies}, etc.: * these arrays have no associated resources. * * @param context the context of execution; can be {@code null}, then it will be ignored. * @see #freeResources(ArrayContext) * @see #flushResources(ArrayContext) * @see #flushResources(ArrayContext, boolean) */ void loadResources(ArrayContext context); /** * Equivalent to {@link #flushResources(ArrayContext, boolean) flushResources}(null, false). * This is the most typical case of flushing resources. * * @see #loadResources(ArrayContext) * @see #freeResources(ArrayContext) */ default void flushResources() { flushResources(null, false); } /** * Equivalent to {@link #flushResources(ArrayContext, boolean) flushResources}(context, false). * * @param context the context of execution; can be {@code null}, then it will be ignored. * @see #loadResources(ArrayContext) * @see #freeResources(ArrayContext) */ default void flushResources(ArrayContext context) { flushResources(context, false); } /** * If there are some external resources, associated with this array, — * files, streams, sockets, locks, etc. — * and some array data are not still reflected in that resources * (for example, were not saved in the disk file yet), * this method flushes all these data to the external devices. * *

This method may not perform immediate writing data to the storage devices. * But it guarantees that:

    * *
  1. if some AlgART array will be created and associated with the same resources as this array * — for example, will be mapped to the same external file — all data stored * in this array will be "visible" in the new array; *
     
  2. * *
  3. if this array is a view of some external resource, that is not "temporary" * (i.e. will not be automatically deleted after shutting down JVM), * then all changes, made in this array, will be really stored in that resource * and will be able to be loaded by another software, at least, after shutting down JVM. *
  4. *
* *

If forcePhysicalWriting argument is false, this method works as quick as possible. * *

If forcePhysicalWriting argument is true, this * method tries to physically flush all unsaved elements of this array to the storage device. * The precise actions, performed in this case, are not specified. * The typical behavior: all internal caches, if they are provided by Java implementation of the AlgART array, * are written to the external device via OS calls, and OS is requested to flush buffers or file-mapping * to the physical disk. * The mode forcePhysicalWriting=true increases chances that the data will be really flushed to * external devices and, so, OS will release physical memory, which was probably used for disk or another cache. * This mode also increases chances that all changes, made in this array until this moment, * will be immediately "visible" in another software (another OS process) as changes in the corresponding * external resources (for example, in the disk file). * *

If the resources, associated with this array, are shared with some another arrays * (usually when one array is a view of another one), this method still * does flush these resource. * *

You may use {@link #subArray(long, long)} / {@link #subArr(long, long)} methods * to flush any portion of this array, for example:

     *     array.subArr(destPos, count).flushResources(context, false);
*

But there is no guarantee that flushing a subarray will not lead to flushing some other * parts of the source array. * *

In particular, please note: this method may do something even for immutable arrays. * If an array is an {@link #asImmutable() immutable view} of another array a, * flushing this view is equivalent to flushing the original array a. * *

The context argument is necessary to allow user to interrupt this method and to view * the execution progress. Namely, if this argument is not {@code null}, this method probably calls * context.{@link ArrayContext#checkInterruption() checkInterruption} and * context.{@link ArrayContext#updateProgress updateProgress} methods from time to time. * It may be useful if this array is very large and writing non-flushed data to an external device * requires a long time. For example, it is possible for arrays, created by * {@link LargeMemoryModel#newLazyCopy(Array) LargeMemoryModel.newLazyCopy} method. * You always may pass {@code null} as this argument; then all will work correctly, * but, maybe, the user will be bored for some time. * *

This method does nothing for arrays created by the {@link SimpleMemoryModel simple memory model} * and the {@link BufferMemoryModel buffer memory model}, and also for constant arrays * created by {@link Arrays#nByteCopies}, {@link Arrays#nCharCopies}, etc.: * these arrays have no associated resources. * *

All operations, performed by this method, are also performed by * {@link #freeResources(ArrayContext, boolean)} method with * the same forcePhysicalWriting argument. * *

Performance note: please avoid sequential calls of this method, like the following:

     *     array.flushResources(null, false);
     *     array.flushResources(null, false); // - unnecessary call
     * 
*

The second call here is not necessary, because all data are already flushed while the first call — * however, it is still possible that the second call will spend time for writing data again t * o an external device. * * @param context the context of execution; can be {@code null}, then it will be ignored. * @param forcePhysicalWriting is it necessary to try forcing physical writing all associated resources * to the external device. * @see #loadResources(ArrayContext) * @see #flushResources(ArrayContext) * @see #freeResources(ArrayContext, boolean) * @see Matrix#flushResources(ArrayContext) */ void flushResources(ArrayContext context, boolean forcePhysicalWriting); /** * Equivalent to {@link #freeResources(ArrayContext, boolean) freeResources}(null, false). * This is the most typical case of freeing resources. * * @see #loadResources(ArrayContext) * @see #flushResources(ArrayContext) * @see Matrix#freeResources() */ default void freeResources() { freeResources(null, false); } /** * Equivalent to {@link #freeResources(ArrayContext, boolean) freeResources}(context, false). * * @param context the context of execution; can be {@code null}, then it will be ignored. * @see #loadResources(ArrayContext) * @see #flushResources(ArrayContext) * @see Matrix#freeResources(ArrayContext) */ default void freeResources(ArrayContext context) { freeResources(context, false); } /** * If there are some resources, associated with this array, which are not controlled * by Java garbage collectors — files, streams, sockets, locks, etc. — * this method tries to release them (for example, to close any files). * However, the array stays alive: if the resources will be necessary for following array operations, * they will be automatically re-acquired. * *

As a part of the work, this method always performs the same actions as * {@link #flushResources(ArrayContext, boolean) flushResources}(context, forcePhysicalWriting) * call with the same forcePhysicalWriting argument. See comments to that method for more details * about flushing external resources. * *

This method guarantees that any changes, made after its call in any external resources, * associated with this array, will be "visible" in this array while any accesses to it * after these changes. For example, if this array is a view of some disk file, * you need to call this method to be sure that any changes, performed in the file * by another application after this call and before the next access to this array, * will be successfully reflected in this array. * *

If the resources, associated with this array, are shared with some another arrays * (usually when one array is a view of another one), this method still * does release these resource. * It means that calling this method can slow down the next access not only to this array, * but also to another ones, for example, to its {@link #subArray(long, long) subarrays}. * *

The context argument is necessary to allow user to interrupt this method and to view * the execution progress. Namely, if this argument is not {@code null}, this method probably calls * context.{@link ArrayContext#checkInterruption() checkInterruption} and * context.{@link ArrayContext#updateProgress updateProgress} methods from time to time. * It may be useful if this array is very large and writing non-flushed data to an external device * requires a long time. For example, it is possible for arrays, created by * {@link LargeMemoryModel#newLazyCopy(Array) LargeMemoryModel.newLazyCopy} method. * You always may pass {@code null} as this argument; then all will work correctly, * but, maybe, the user will be bored for some time. * *

This method does nothing for arrays created by the {@link SimpleMemoryModel simple memory model} * and the {@link BufferMemoryModel buffer memory model}, and also for constant arrays * created by {@link Arrays#nByteCopies Arrays.nByteCopies}, {@link Arrays#nCharCopies Arrays.nCharCopies}, etc.: * these arrays have no associated resources. * *

Performance note 1: you may use the call

     *     array.{@link #subArray(long, long) subArray(0,0)}.freeResources(null, false)
     * 
* to release all resources, associated with the original array. * It may work faster than simple * "array.freeResources(null,false)", * because there is no necessity to flush all array elements: * releasing a subarray requires flushing only the subarray elements, * i.e., no elements in a case of the zero-length subarray. * This speeding-up is guaranteed for arrays, created by {@link LargeMemoryModel large memory model}, * but is not guaranteed for other arrays: it is still possible that * "array.{@link #subArray(long, long) subArray(0,0)}.freeResources(context,false)" * call will flush all array data. * *

Performance note 2: please avoid calling {@link #flushResources(ArrayContext, boolean)} * together with this method:

     *     array.flushResources(null, false); // - unnecessary call
     *     array.freeResources(null, false);
     * 
*

or

     *     array.flushResources(null, true);
     *     array.freeResources(null);
     *     // - it's much better to use a single call "array.freeResources(null, true)"
     * 
*

It is very possible that the call of freeResources method will spend time for flushing data again, * though they were already flushed by the previous flushResources method. * If is much better to perform all the work in a single call of this method with the corresponding * forcePhysicalWriting argument. * *

All resources allocated by this package are automatically released and — * for temporary resources, i.e. garbage, — * removed (as it is possible) by built-in cleanup procedures while JVM termination. * However, we recommend to directly call * freeResources(context) at the end of methods * that create and process large AlgART arrays. * The reason is that if there will be a lot of non-released large arrays, the automatic cleanup procedure * may strongly reduce the speed of closing the application. * *

Important: you must use this method if you are working with some collection * (like java.util.List or a usual Java array) of large AlgART arrays * (each per many megabytes or gigabytes) and if this collection contains many elements: * more than several tens. If an AlgART array has some associated resources, for example, * like arrays created by {@link LargeMemoryModel} and mapped on a disk file, then every such instance * usually occupies some RAM (and also, maybe, OS address space for mapping), * usually up to several tens of megabytes (for large arrays) for caching and similar needs. * This RAM cannot be automatically released by the garbage collector until you call this method. * So, you must manually release all resources by calling this method every time, * when this array is already not necessary, but should be stored in some collection for the future. * In another case, thousands of inactive instances of AlgART arrays with non-released resources * can exhaust all available RAM (or address space). * * @param context the context of execution; can be {@code null}, then it will be ignored. * @param forcePhysicalWriting is it necessary to try forcing physical writing all associated resources * to the external device. * @see #loadResources(ArrayContext context) * @see #flushResources(ArrayContext context, boolean forcePhysicalWriting) * @see #freeResources(ArrayContext) * @see Arrays#freeAllResources() */ void freeResources(ArrayContext context, boolean forcePhysicalWriting); /** * Returns a brief string description of this object. * *

The result of this method may depend on implementation and usually contains * a short description of the array length, capacity, element type. * *

Note: for {@link CharArray character arrays}, unlike CharSequence.toString(), * this method works as for all other array types. * If you need to convert a character array to a string, * containing all characters of the array, you may use * {@link Arrays#toString(CharArray)} method. * * @return a brief string description of this object. */ String toString(); /** * Returns the hash code of this array. The result depends on all elements of the array * (from element #0 to element #{@link #length()}-1). * *

For non-primitive element type ({@link ObjectArray}, {@link UpdatableObjectArray}, * {@link MutableObjectArray} subinterfaces), the result is always based on implementation * of hashCode method in the class of elements ({@link #elementType()}). * * @return the hash code of this array. */ int hashCode(); /** * Indicates whether some other array is equal to this one. * Returns true if and only if:

    *
  1. the specified object is an array (i.e. implements {@link Array}),
  2. *
  3. both arrays have the same {@link #length() length},
  4. *
  5. for arrays of primitive elements * ({@link BitArray}, {@link CharArray}, * {@link ByteArray}, {@link ShortArray}, * {@link IntArray}, {@link LongArray}, * {@link FloatArray}, {@link DoubleArray}): * both arrays have the same {@link #elementType() element type} * and all corresponding pairs of elements are equal * (for float and double elements, * unlike the == operator, this method considers * NaN equals to itself, and 0.0 unequal to -0.0);
  6. *
  7. for non-primitive arrays (when both arrays implement {@link ObjectArray}), * the method may check one from two following conditions * (only 1st or only 2nd, depending on implementation):
      *
    • both arrays have the same {@link #elementType() element type} * and all corresponding pairs of elements contain identical data * (equals method of the class of elements * is not used in this case: {@link CombinedMemoryModel combined arrays} are an example);
    • *
    • for all corresponding pairs of elements e1, e2 * (e1 is an element #i of this array, * e2 is an element #i of the obj argument, * i=0,1,...,{@link #length() length()}-1), the following check returns true: * (e1==null ? e2==null : e1.equals(e2)).
    • *
  8. *
* * @param obj the object to be compared for equality with this array. * @return true if the specified object is an array equal to this one. */ boolean equals(Object obj); /** * Equivalent to {@link MemoryModel#newUnresizableArray(Class, long) * memoryModel.newUnresizableArray(elementType, length)}. * * @param memoryModel the memory model, used for allocation new array. * @param elementType the type of array elements. * @param length the length and capacity of the array. * @return created unresizable AlgART array. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if elementType is void.class * or if the specified length is negative. * @throws UnsupportedElementTypeException if elementType is not supported by this memory model. * @throws TooLargeArrayException if the specified length is too large for this memory model. */ static UpdatableArray newArray(MemoryModel memoryModel, Class elementType, long length) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newUnresizableArray(elementType, length); } /** * Equivalent to {@link #newArray(MemoryModel, Class, long) * newArray}({@link Arrays#SMM Arrays.SMM}, elementType, length). * * @param elementType the type of array elements. * @param length the length and capacity of the array. * @return created unresizable AlgART array. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if elementType is void.class * or if the specified length is negative. * @throws TooLargeArrayException if the specified length is too large for {@link SimpleMemoryModel}. */ static UpdatableArray newArray(Class elementType, long length) { return newArray(Arrays.SMM, elementType, length); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy