/*
* Copyright 2015 Goldman Sachs.
*
* Licensed 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 com.gs.collections.impl.list.immutable.primitive;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.BitSet;
import java.util.NoSuchElementException;
import com.gs.collections.api.BooleanIterable;
import com.gs.collections.api.LazyBooleanIterable;
import com.gs.collections.api.bag.primitive.MutableBooleanBag;
import com.gs.collections.api.block.function.primitive.BooleanToObjectFunction;
import com.gs.collections.api.block.function.primitive.ObjectBooleanIntToObjectFunction;
import com.gs.collections.api.block.function.primitive.ObjectBooleanToObjectFunction;
import com.gs.collections.api.block.predicate.primitive.BooleanPredicate;
import com.gs.collections.api.block.procedure.primitive.BooleanIntProcedure;
import com.gs.collections.api.block.procedure.primitive.BooleanProcedure;
import com.gs.collections.api.iterator.BooleanIterator;
import com.gs.collections.api.list.ImmutableList;
import com.gs.collections.api.list.primitive.BooleanList;
import com.gs.collections.api.list.primitive.ImmutableBooleanList;
import com.gs.collections.api.list.primitive.MutableBooleanList;
import com.gs.collections.api.set.primitive.MutableBooleanSet;
import com.gs.collections.impl.bag.mutable.primitive.BooleanHashBag;
import com.gs.collections.impl.factory.primitive.BooleanLists;
import com.gs.collections.impl.lazy.primitive.LazyBooleanIterableAdapter;
import com.gs.collections.impl.lazy.primitive.ReverseBooleanIterable;
import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.list.mutable.primitive.BooleanArrayList;
import com.gs.collections.impl.set.mutable.primitive.BooleanHashSet;
import net.jcip.annotations.Immutable;
/**
* ImmutableBooleanArrayList is the non-modifiable equivalent of {@link BooleanArrayList}.
* It is backed by a {@link BitSet}.
*
* @since 3.2.
*/
@Immutable
final class ImmutableBooleanArrayList
implements ImmutableBooleanList, Serializable
{
private static final long serialVersionUID = 1L;
private final int size;
private final BitSet items;
private ImmutableBooleanArrayList(boolean[] newElements)
{
if (newElements.length <= 1)
{
throw new IllegalArgumentException("Use BooleanLists.immutable.with() to instantiate an optimized collection");
}
this.size = newElements.length;
this.items = new BitSet(newElements.length);
for (int i = 0; i < newElements.length; i++)
{
if (newElements[i])
{
this.items.set(i);
}
}
}
private ImmutableBooleanArrayList(BitSet newItems, int size)
{
this.size = size;
this.items = newItems;
}
public static ImmutableBooleanArrayList newList(BooleanIterable iterable)
{
return new ImmutableBooleanArrayList(iterable.toArray());
}
public static ImmutableBooleanArrayList newListWith(boolean... elements)
{
return new ImmutableBooleanArrayList(elements);
}
private IndexOutOfBoundsException newIndexOutOfBoundsException(int index)
{
return new IndexOutOfBoundsException("Index: " + index + " Size: " + this.size);
}
public boolean get(int index)
{
if (index < this.size)
{
return this.items.get(index);
}
throw this.newIndexOutOfBoundsException(index);
}
public boolean getFirst()
{
return this.items.get(0);
}
public boolean getLast()
{
return this.items.get(this.size - 1);
}
public int indexOf(boolean value)
{
for (int i = 0; i < this.size; i++)
{
if (this.items.get(i) == value)
{
return i;
}
}
return -1;
}
public int lastIndexOf(boolean value)
{
for (int i = this.size - 1; i >= 0; i--)
{
if (this.items.get(i) == value)
{
return i;
}
}
return -1;
}
public BooleanIterator booleanIterator()
{
return new InternalBooleanIterator();
}
public void forEach(BooleanProcedure procedure)
{
this.each(procedure);
}
/**
* @since 7.0.
*/
public void each(BooleanProcedure procedure)
{
for (int i = 0; i < this.size; i++)
{
procedure.value(this.items.get(i));
}
}
public void forEachWithIndex(BooleanIntProcedure procedure)
{
for (int i = 0; i < this.size; i++)
{
procedure.value(this.items.get(i), i);
}
}
public int count(BooleanPredicate predicate)
{
int count = 0;
for (int i = 0; i < this.size; i++)
{
if (predicate.accept(this.items.get(i)))
{
count++;
}
}
return count;
}
public boolean anySatisfy(BooleanPredicate predicate)
{
for (int i = 0; i < this.size; i++)
{
if (predicate.accept(this.items.get(i)))
{
return true;
}
}
return false;
}
public boolean allSatisfy(BooleanPredicate predicate)
{
for (int i = 0; i < this.size; i++)
{
if (!predicate.accept(this.items.get(i)))
{
return false;
}
}
return true;
}
public boolean noneSatisfy(BooleanPredicate predicate)
{
for (int i = 0; i < this.size; i++)
{
if (predicate.accept(this.items.get(i)))
{
return false;
}
}
return true;
}
public ImmutableBooleanList select(BooleanPredicate predicate)
{
MutableBooleanList result = BooleanLists.mutable.empty();
for (int i = 0; i < this.size; i++)
{
boolean item = this.items.get(i);
if (predicate.accept(item))
{
result.add(item);
}
}
return result.toImmutable();
}
public ImmutableBooleanList reject(BooleanPredicate predicate)
{
MutableBooleanList result = BooleanLists.mutable.empty();
for (int i = 0; i < this.size; i++)
{
boolean item = this.items.get(i);
if (!predicate.accept(item))
{
result.add(item);
}
}
return result.toImmutable();
}
public boolean detectIfNone(BooleanPredicate predicate, boolean ifNone)
{
for (int i = 0; i < this.size; i++)
{
boolean item = this.items.get(i);
if (predicate.accept(item))
{
return item;
}
}
return ifNone;
}
public <V> ImmutableList<V> collect(BooleanToObjectFunction<? extends V> function)
{
FastList<V> target = FastList.newList(this.size);
for (int i = 0; i < this.size; i++)
{
target.add(function.valueOf(this.items.get(i)));
}
return target.toImmutable();
}
public boolean[] toArray()
{
boolean[] newItems = new boolean[this.size];
for (int i = 0; i < this.size; i++)
{
newItems[i] = this.items.get(i);
}
return newItems;
}
public boolean contains(boolean value)
{
for (int i = 0; i < this.size; i++)
{
if (this.items.get(i) == value)
{
return true;
}
}
return false;
}
public boolean containsAll(boolean... source)
{
for (boolean value : source)
{
if (!this.contains(value))
{
return false;
}
}
return true;
}
public boolean containsAll(BooleanIterable source)
{
for (BooleanIterator iterator = source.booleanIterator(); iterator.hasNext(); )
{
if (!this.contains(iterator.next()))
{
return false;
}
}
return true;
}
public LazyBooleanIterable asReversed()
{
return ReverseBooleanIterable.adapt(this);
}
public MutableBooleanList toList()
{
return BooleanArrayList.newList(this);
}
public MutableBooleanSet toSet()
{
return BooleanHashSet.newSet(this);
}
public MutableBooleanBag toBag()
{
return BooleanHashBag.newBag(this);
}
public LazyBooleanIterable asLazy()
{
return new LazyBooleanIterableAdapter(this);
}
public ImmutableBooleanList toImmutable()
{
return this;
}
public ImmutableBooleanArrayList toReversed()
{
return ImmutableBooleanArrayList.newList(this.asReversed());
}
/**
* @since 6.0
*/
public ImmutableBooleanList distinct()
{
BooleanArrayList target = new BooleanArrayList();
MutableBooleanSet seenSoFar = new BooleanHashSet();
for (int i = 0; i < this.size; i++)
{
boolean each = this.get(i);
if (seenSoFar.add(each))
{
target.add(each);
}
}
return target.toImmutable();
}
public ImmutableBooleanList newWith(boolean element)
{
BitSet newItems = (BitSet) this.items.clone();
if (element)
{
newItems.set(this.size);
}
return new ImmutableBooleanArrayList(newItems, this.size + 1);
}
public ImmutableBooleanList newWithout(boolean element)
{
int index = this.indexOf(element);
if (index != -1)
{
boolean[] newItems = new boolean[this.size - 1];
for (int i = 0; i < index; i++)
{
newItems[i] = this.items.get(i);
}
for (int i = index + 1; i < this.size; i++)
{
newItems[i - 1] = this.items.get(i);
}
return BooleanLists.immutable.with(newItems);
}
return this;
}
public ImmutableBooleanList newWithAll(BooleanIterable elements)
{
BitSet newItems = (BitSet) this.items.clone();
int index = 0;
for (BooleanIterator booleanIterator = elements.booleanIterator(); booleanIterator.hasNext(); index++)
{
if (booleanIterator.next())
{
newItems.set(this.size + index);
}
}
return new ImmutableBooleanArrayList(newItems, this.size + elements.size());
}
public ImmutableBooleanList newWithoutAll(BooleanIterable elements)
{
MutableBooleanList list = this.toList();
list.removeAll(elements);
return list.toImmutable();
}
public int size()
{
return this.size;
}
public boolean isEmpty()
{
return false;
}
public boolean notEmpty()
{
return true;
}
@Override
public boolean equals(Object otherList)
{
if (otherList == this)
{
return true;
}
if (!(otherList instanceof BooleanList))
{
return false;
}
BooleanList list = (BooleanList) otherList;
if (this.size != list.size())
{
return false;
}
for (int i = 0; i < this.size; i++)
{
if (this.items.get(i) != list.get(i))
{
return false;
}
}
return true;
}
@Override
public int hashCode()
{
int hashCode = 1;
for (int i = 0; i < this.size; i++)
{
boolean item = this.items.get(i);
hashCode = 31 * hashCode + (item ? 1231 : 1237);
}
return hashCode;
}
public <T> T injectInto(T injectedValue, ObjectBooleanToObjectFunction<? super T, ? extends T> function)
{
T result = injectedValue;
for (int i = 0; i < this.size; i++)
{
result = function.valueOf(result, this.items.get(i));
}
return result;
}
public <T> T injectIntoWithIndex(T injectedValue, ObjectBooleanIntToObjectFunction<? super T, ? extends T> function)
{
T result = injectedValue;
for (int i = 0; i < this.size; i++)
{
result = function.valueOf(result, this.items.get(i), i);
}
return result;
}
@Override
public String toString()
{
return this.makeString("[", ", ", "]");
}
public String makeString()
{
return this.makeString(", ");
}
public String makeString(String separator)
{
return this.makeString("", separator, "");
}
public String makeString(String start, String separator, String end)
{
Appendable stringBuilder = new StringBuilder();
this.appendString(stringBuilder, start, separator, end);
return stringBuilder.toString();
}
public void appendString(Appendable appendable)
{
this.appendString(appendable, ", ");
}
public void appendString(Appendable appendable, String separator)
{
this.appendString(appendable, "", separator, "");
}
public void appendString(
Appendable appendable,
String start,
String separator,
String end)
{
try
{
appendable.append(start);
for (int i = 0; i < this.size; i++)
{
if (i > 0)
{
appendable.append(separator);
}
boolean value = this.items.get(i);
appendable.append(String.valueOf(value));
}
appendable.append(end);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public ImmutableBooleanList subList(int fromIndex, int toIndex)
{
throw new UnsupportedOperationException("subList not yet implemented!");
}
private Object writeReplace()
{
return new ImmutableBooleanListSerializationProxy(this);
}
private static class ImmutableBooleanListSerializationProxy implements Externalizable
{
private static final long serialVersionUID = 1L;
private ImmutableBooleanList list;
public ImmutableBooleanListSerializationProxy()
{
// Empty constructor for Externalizable class
}
private ImmutableBooleanListSerializationProxy(ImmutableBooleanList list)
{
this.list = list;
}
public void writeExternal(ObjectOutput out) throws IOException
{
out.writeInt(this.list.size());
for (int i = 0; i < this.list.size(); i++)
{
out.writeBoolean(this.list.get(i));
}
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
int inputSize = in.readInt();
BitSet newItems = new BitSet(inputSize);
for (int i = 0; i < inputSize; i++)
{
newItems.set(i, in.readBoolean());
}
this.list = new ImmutableBooleanArrayList(newItems, inputSize);
}
protected Object readResolve()
{
return this.list;
}
}
private class InternalBooleanIterator implements BooleanIterator
{
/**
* Index of element to be returned by subsequent call to next.
*/
private int currentIndex;
public boolean hasNext()
{
return this.currentIndex != ImmutableBooleanArrayList.this.size;
}
public boolean next()
{
if (!this.hasNext())
{
throw new NoSuchElementException();
}
boolean next = ImmutableBooleanArrayList.this.get(this.currentIndex);
this.currentIndex++;
return next;
}
}
}