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

org.jgroups.util.FastArray Maven / Gradle / Ivy

There is a newer version: 5.4.1.Final
Show newest version
package org.jgroups.util;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * Simple 
unsynchronized
array. The array can only grow, but never shrinks (no arraycopy()). Elements * are removed by nulling them. A size variable is maintained for quick size() / isEmpty(). * @author Bela Ban * @since 5.2 */ public class FastArray implements Iterable { protected T[] elements; protected int index; // position at which the next element is inserted; only increments, never decrements protected int size; // size: basically index - null elements protected int increment=5; protected int print_limit=20; // max numnber of elements to be printed in toString public FastArray(int capacity) { elements=(T[])new Object[capacity]; } public int capacity() {return elements.length;} public int index() {return index;} public int size() {return size;} public boolean isEmpty() {return size == 0;} public int increment() {return increment;} public FastArray increment(int i) {this.increment=ensurePositive(i); return this;} public int printLimit() {return print_limit;} public FastArray printLimit(int l) {this.print_limit=l; return this;} public int add(T el) { return add(el, true); } public int add(T el, boolean resize) { if(el == null) return 0; if(index == elements.length) { if(!resize) return 0; resize(index + increment); } elements[index++]=el; size++; return 1; } /** * Adds elements from an array els to this array * @param els The other array, can have null elements * @param length The number of elements to add. must be <= els.length * @return The number of elements added */ public int add(T[] els, int length) { if(els == null) return 0; if(length > els.length) length=els.length; if(index + length > elements.length) resize(index + length + increment); System.arraycopy(els, 0, elements, index, length); int added=0, end_index=index+length; while(index < end_index) { if(elements[index++] != null) added++; } size+=added; return added; } @SafeVarargs public final int add(T... els) { return els == null? 0 : add(els, els.length); } public int add(Collection list) { if(list == null) return 0; int list_size=list.size(); if(index + list_size > elements.length) resize(index + list_size + increment); int old_size=size; for(T el: list) { if(el != null) { // null elements need to be handled elements[index++]=el; size++; } } return size - old_size; } public int add(FastArray fa) { return add(fa, true); } public int add(FastArray fa, boolean resize) { if(fa == null) return 0; if(this == fa) throw new IllegalArgumentException("cannot add FastArray to itself"); int fa_size=fa.size(); if(index+fa_size > elements.length && resize) resize(index + fa_size + increment); int old_size=size; for(T el: fa) { if(index >= elements.length) return size-old_size; elements[index++]=el; // no need to handle null elements; the iterator skips null elements size++; } return size-old_size; } /** * Copies the messages from the other array into this one,
including
null elements * (using {@link System#arraycopy(Object, int, Object, int, int)}. This is the same as calling {@link #clear(boolean)} * followed by {@link #add(FastArray, boolean)}, but supposedly faster. * @param other The other array * @param clear Clears the other array after the transfer when true * @return The number of non-null elements transferred from other */ public int transferFrom(FastArray other, boolean clear) { if(other == null || this == other) return 0; int capacity=elements.length, other_size=other.size(), other_capacity=other.capacity(); if(other_size == 0) return 0; if(capacity < other_capacity) elements=Arrays.copyOf(other.elements, other_capacity); else System.arraycopy(other.elements, 0, this.elements, 0, other_capacity); if(this.index > other.index) for(int i=other.index; i < this.index; i++) elements[i]=null; this.index=other.index; this.size=other_size; // not all other.elements may have been 0 if(clear) other.clear(true); return other_size; } public T get(int idx) { if(idx < 0 || idx >= this.index) return null; return elements[idx]; } public FastArray set(int idx, T el) { if(idx < 0 || idx >= this.index) return this; T old_el=elements[idx]; if(old_el == null) { if(el != null) size++; } else { if(el == null) size--; } elements[idx]=el; return this; } public FastArray set(T[] elements) { this.elements=Objects.requireNonNull(elements); index=elements.length; size=count(); return this; } public boolean anyMatch(Predicate pred) { if(pred == null) return false; for(Iterator it=iterator(); it.hasNext();) { T el=it.next(); if(el != null && pred.test(el)) return true; } return false; } public FastArray remove(int idx) { return set(idx, null); } public FastArray removeIf(Predicate filter, boolean replace_all) { return replaceIf(filter, null, replace_all); } /** * Replaces any or all elements matching filter with a new element * @param filter The filter, must ne non-null or no replacements will take place * @param new_el The new element, can be null * @param replace_all When false, the method returns after the first match (if any). Otherwise, all matching * elements are replaced */ public FastArray replaceIf(Predicate filter, T new_el, boolean replace_all) { if(filter == null) return this; for(FastIterator it=iterator(filter); it.hasNext();) { it.next(); it.replace(new_el); if(!replace_all) break; } return this; } public FastArray clear(boolean null_elements) { if(null_elements) for(int i=0; i < index; i++) elements[i]=null; index=size=0; return this; } /** Iterator which iterates only over non-null elements, skipping null elements */ public FastIterator iterator() { return new FastIterator(null); } /** Iterates over all non-null elements which match filter */ public FastIterator iterator(Predicate filter) { return new FastIterator(filter); } public Stream stream() { Spliterator sp=Spliterators.spliterator(iterator(), size, 0); return StreamSupport.stream(sp, false); } /** Returns the number of non-null elements, should have the same result as size(). Only used for testing! */ public int count() { int cnt=0; for(int i=0; i < index; i++) { if(elements[i] != null) cnt++; } return cnt; } public String toString() { return String.format("%d elements (cap=%d): [%s]", size, capacity(), print()); } public String print() { return print(print_limit); } public FastArray resize(int new_capacity) { if(new_capacity <= elements.length) return this; elements=Arrays.copyOf(elements, new_capacity); return this; } protected String print(int limit) { boolean first=true; StringBuilder sb=new StringBuilder(); int count=0; for(T el: elements) { if(first) first=false; else sb.append(", "); sb.append(el); if(limit > 0 && ++count >= limit) return sb.append(" ...").toString(); } return sb.toString(); } protected static int ensurePositive(int i) { if(i < 1) throw new IllegalArgumentException("value needs to be >= 1"); return i; } public class FastIterator implements Iterator { protected int current_index=-1; protected final Predicate filter; protected int hit_count; // number of non-null elements public FastIterator(Predicate filter) { this.filter=filter; } public boolean hasNext() { // skip null msgs or msgs that don't match the filter (if set) while(current_index +1 < index && hit_count < size && nullOrNoFilterMatch(current_index+1)) current_index++; return current_index +1 < index && hit_count < size; } public T next() { if(current_index +1 >= index) throw new NoSuchElementException(); hit_count++; return elements[++current_index]; } public void remove() { replace(null); } public void replace(T el) { if(current_index >= 0) { int old_size=size; set(current_index, el); if(size < old_size) hit_count=Math.max(hit_count-1, 0); } } public int currentIndex() {return current_index;} public int hitCount() {return hit_count;} protected boolean nullOrNoFilterMatch(int index) { if(elements[index] == null) return true; boolean result=filter != null && filter.test(elements[index]) == false; if(result) hit_count++; return result; } public String toString() { return String.format("curr-index=%d hit-count=%d", current_index, hit_count); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy