blob: 27f5dfc13b5a22366d7ac8905adee20b01634426 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.util;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.NoSuchElementException;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.SB;
import static org.apache.ignite.internal.util.IgniteUtils.EMPTY_LONGS;
/**
* Minimal list API to work with primitive longs. This list exists
* to avoid boxing/unboxing when using standard list from Java.
*/
public class GridLongList implements Externalizable {
/** */
private static final long serialVersionUID = 0L;
/** */
private long[] arr;
/** */
private int idx;
/**
*
*/
public GridLongList() {
// No-op.
}
/**
* @param size Size.
*/
public GridLongList(int size) {
arr = new long[size];
// idx = 0
}
/**
* @param arr Array.
*/
public GridLongList(long[] arr) {
this.arr = arr;
idx = arr.length;
}
/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof GridLongList))
return false;
GridLongList that = (GridLongList)o;
if (idx != that.idx)
return false;
if (idx == 0 || arr == that.arr)
return true;
for (int i = 0; i < idx; i++) {
if (arr[i] != that.arr[i])
return false;
}
return true;
}
/** {@inheritDoc} */
@Override public int hashCode() {
int res = 1;
for (int i = 0; i < idx; i++) {
long element = arr[i];
int elementHash = (int)(element ^ (element >>> 32));
res = 31 * res + elementHash;
}
return res;
}
/**
* @param l List to add all elements of.
*/
public void addAll(GridLongList l) {
assert l != null;
if (l.isEmpty())
return;
if (arr == null)
arr = new long[4];
int len = arr.length;
while (len < idx + l.size())
len <<= 1;
arr = Arrays.copyOf(arr, len);
System.arraycopy(l.arr, 0, arr, idx, l.size());
idx += l.size();
}
/**
* Add element to this array.
* @param x Value.
*/
public void add(long x) {
if (arr == null)
arr = new long[4];
else if (arr.length == idx)
arr = Arrays.copyOf(arr, Math.max(1, arr.length) << 1);
arr[idx++] = x;
}
/**
* Clears the list.
*/
public void clear() {
idx = 0;
}
/**
* Removes and returns the last element of the list. Complementary method to {@link #add(long)} for stack like usage.
*
* @return Removed element.
* @throws NoSuchElementException If the list is empty.
*/
public long remove() throws NoSuchElementException {
if (idx == 0)
throw new NoSuchElementException();
return arr[--idx];
}
/**
* @param i Index.
* @return Value.
*/
public long get(int i) {
assert i < idx;
return arr[i];
}
/**
* @return Size.
*/
public int size() {
return idx;
}
/**
* @return Array.
*/
public long[] array() {
return arr;
}
/**
* @return {@code True} if this list has no elements.
*/
public boolean isEmpty() {
return idx == 0;
}
/**
* @param l Element to find.
* @return {@code True} if found.
*/
public boolean contains(long l) {
for (int i = 0; i < idx; i++) {
if (arr[i] == l)
return true;
}
return false;
}
/**
* @param size New size.
* @param last If {@code true} the last elements will be removed, otherwise the first.
*/
public void truncate(int size, boolean last) {
assert size >= 0 && size <= idx;
if (size == idx)
return;
if (!last && size != 0)
System.arraycopy(arr, idx - size, arr, 0, size);
idx = size;
}
/**
* Removes element by given index.
*
* @param i Index.
* @return Removed value.
*/
public long removeIndex(int i) {
assert i < idx : i;
long res = arr[i];
if (i == idx - 1) { // Last element.
idx = i;
}
else {
System.arraycopy(arr, i + 1, arr, i, idx - i - 1);
idx--;
}
return res;
}
/**
* Removes value from this list.
*
* @param startIdx Index to begin search with.
* @param val Value.
* @return Index of removed value if the value was found and removed or {@code -1} otherwise.
*/
public int removeValue(int startIdx, long val) {
assert startIdx >= 0;
for (int i = startIdx; i < idx; i++) {
if (arr[i] == val) {
removeIndex(i);
return i;
}
}
return -1;
}
/**
* @return Array copy.
*/
public long[] arrayCopy() {
if (arr == null)
return EMPTY_LONGS;
long[] res = new long[idx];
System.arraycopy(arr, 0, res, 0, idx);
return res;
}
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(idx);
for (int i = 0; i < idx; i++)
out.writeLong(arr[i]);
}
/** {@inheritDoc} */
@Override public void readExternal(ObjectInput in) throws IOException {
idx = in.readInt();
arr = new long[idx];
for (int i = 0; i < idx; i++)
arr[i] = in.readLong();
}
/** {@inheritDoc} */
@Override public String toString() {
SB b = new SB("[");
for (int i = 0; i < idx; i++) {
if (i != 0)
b.a(',');
b.a(arr[i]);
}
b.a(']');
return S.toString(GridLongList.class, this, "arr", b);
}
/**
* Sorts this list.
* Use {@code copy().sort()} if you need a defensive copy.
*
* @return {@code this} For chaining.
*/
public GridLongList sort() {
if (idx > 1)
Arrays.sort(arr, 0, idx);
return this;
}
}