Skip to content

Instantly share code, notes, and snippets.

@calvernaz
Last active February 2, 2017 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save calvernaz/d60569c344a5c3202981d2ade4811763 to your computer and use it in GitHub Desktop.
Save calvernaz/d60569c344a5c3202981d2ade4811763 to your computer and use it in GitHub Desktop.
Fluent Immutable List
package com.util.collections;
import static com.google.common.collect.FluentIterable.from;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fsg.prizebonds.util.executor.Executor;
import com.fsg.prizebonds.util.mutation.Mutation;
import com.fsg.prizebonds.util.specification.Specification;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@JsonIgnoreProperties(ignoreUnknown = true)
public class FluentImmutableList<T> implements Iterable<T> {
@JsonProperty("items")
protected final ImmutableList<T> items;
public static <T> FluentImmutableList<T> emptyList() {
return new FluentImmutableList<>();
}
public FluentImmutableList(T t) {
this.items = ImmutableList.of(t);
}
public FluentImmutableList(FluentImmutableList<T> items) {
this(items.items);
}
@JsonCreator
public FluentImmutableList(@JsonProperty("items") Collection<T> items) {
if (items == null) {
items = Collections.emptyList();
}
this.items = ImmutableList.copyOf(items);
}
protected FluentImmutableList() {
this(new ArrayList<T>());
}
public FluentImmutableList(Iterable<T> iterables) {
this(ImmutableList.copyOf(iterables));
}
@Override
public Iterator<T> iterator() {
return items.iterator();
}
@JsonIgnore
public boolean isEmpty() {
return items.isEmpty();
}
@JsonIgnore
public int size() {
return items.size();
}
@JsonIgnore
public Set<T> toSet() {
return new HashSet<>(items);
}
@JsonIgnore
public ImmutableList<T> toList() {
return items.asList();
}
@JsonIgnore
public Optional<T> tryPluck(T toMatch) {
return from(items).firstMatch(new EqualsMatching<>(toMatch));
}
@JsonIgnore
public T pluck(T toMatch) {
return tryPluck(toMatch).orNull();
}
@JsonIgnore
public boolean isPresent(T t) {
return tryPluck(t).isPresent();
}
protected FluentImmutableList<T> differenceWith(FluentImmutableList<T> other) {
return new FluentImmutableList<>(Sets.difference(toSet(), other.toSet()));
}
protected FluentImmutableList<T> unionWith(FluentImmutableList<T> other) {
return new FluentImmutableList<>(Sets.union(toSet(), other.toSet()));
}
protected FluentImmutableList<T> filter(Predicate<T> predicate) {
return new FluentImmutableList<>(from(items).filter(predicate)
.toList());
}
protected FluentImmutableList<T> uniqueHammers() {
return new FluentImmutableList<>(toSet());
}
protected FluentImmutableList<T> addItem(T t) {
if (t == null) return this;
ImmutableList<T> newHammers = ImmutableList.<T>builder()
.addAll(items)
.add(t)
.build();
return new FluentImmutableList<>(newHammers);
}
protected FluentImmutableList<T> removeItem(T t) {
if (t == null) return this;
Collection<T> filtered = Collections2.filter(items, Predicates.not(Predicates.equalTo(t)));
return new FluentImmutableList<>(filtered);
}
protected Collection<T> removeItems(Collection<T> toRemove) {
return Collections2.filter(items, Predicates.not(Predicates.in(toRemove)));
}
public <Y> ImmutableList<Y> transform(Function<T, Y> function) {
return from(items).transform(function)
.toList();
}
protected FluentImmutableList<T> concat(Iterable<? extends FluentImmutableList<T>> collections) {
FluentImmutableList<T> merged = new FluentImmutableList<>();
for (FluentImmutableList<T> collection : collections) {
merged = merged.concat(collection);
}
return merged;
}
protected FluentImmutableList<T> concat(FluentImmutableList<T> collection) {
if (collection == null) return this;
return new FluentImmutableList<>(Iterables.concat(this, collection));
}
protected FluentImmutableList union(T t) {
if (t == null) return this;
return this.concat(new FluentImmutableList<>(t));
}
@JsonIgnore
public FluentImmutableList<T> concat(Collection<T> items) {
return concat(new FluentImmutableList<>(items));
}
@JsonIgnore
public FluentImmutableList<T> mutateUsing(Mutation<T> mutation) {
for (T t : items) {
mutation.mutate(t);
}
return this;
}
@JsonIgnore
public FluentImmutableList<T> executeUsing(Executor<T> executor) {
for (T t : items) {
executor.execute(t);
}
return this;
}
@JsonIgnore
public T first() {
return firstOr(null);
}
@JsonIgnore
public T firstOr(T defaultValue) {
return Iterables.getFirst(items, defaultValue);
}
@JsonIgnore
public T last() {
return lastOr(null);
}
@JsonIgnore
public T lastOr(T defaultValue) {
return Iterables.getLast(items, defaultValue);
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof FluentImmutableList)) return false;
FluentImmutableList<T> rhs = (FluentImmutableList<T>) obj;
return new EqualsBuilder().append(items, rhs.items)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(3, 11).append(items)
.toHashCode();
}
@JsonIgnore
public Optional<T> firstMatch(Specification<T> spec) {
return from(items).firstMatch(spec);
}
@JsonIgnore
public T getAt(int index) {
return items.get(index);
}
@JsonIgnore
public T getFirstMatch(Specification<T> spec) {
Optional<T> firstMatch = firstMatch(spec);
if (!firstMatch.isPresent()) {
throw new IllegalStateException("No matching item from given specification");
}
return firstMatch.get();
}
@JsonIgnore
public boolean contains(T t) {
if (isEmpty()) return false;
return items.contains(t);
}
@JsonIgnore
public boolean containsAll(FluentImmutableList<T> others) {
if (isEmpty()) return false;
if (others.isEmpty()) return false;
return items.containsAll(others.items);
}
@JsonIgnore
public Stream<T> stream() {
return items.stream();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment