Skip to content

Instantly share code, notes, and snippets.

@froop
Last active August 29, 2015 13:57
Show Gist options
  • Save froop/9561953 to your computer and use it in GitHub Desktop.
Save froop/9561953 to your computer and use it in GitHub Desktop.
[Java] 不変コレクション
/**
* 変更不可(イミュータブル)なCollection.
* @param <E> Element: Collection要素の型
* @param <C> Collection: Collectionの型
*/
public abstract class ImmutableCollection<E, C extends Collection<E>>
implements Iterable<E> {
/** Unmodifiable */
private final C raw;
public ImmutableCollection(Collection<E> raw) {
if (raw == null) {
this.raw = createEmpty();
} else {
this.raw = toUnmodifiable(copy(raw));
}
}
public C toRaw() {
return copy(raw);
}
protected abstract C createEmpty();
protected abstract C copy(Collection<E> source);
protected abstract C toUnmodifiable(C source);
@Override
public Iterator<E> iterator() {
return raw.iterator();
}
public int size() {
return raw.size();
}
public boolean isEmpty() {
return raw.isEmpty();
}
public boolean contains(E o) {
return raw.contains(o);
}
@Override
public int hashCode() {
return raw.hashCode();
}
@Override
public boolean equals(Object obj) {
return (obj instanceof ImmutableCollection) && is(cast(obj));
}
@SuppressWarnings("unchecked")
private ImmutableCollection<E, C> cast(Object obj) {
return (ImmutableCollection<E, C>) obj;
}
public boolean is(ImmutableCollection<E, C> obj) {
return (obj != null) && raw.equals(obj.raw);
}
@Override
public String toString() {
return raw.toString();
}
}
/**
* 変更不可(イミュータブル)なList.
* @param <E> Element: List要素の型
*/
public class ImmutableList<E> extends ImmutableCollection<E, List<E>> {
public ImmutableList(Collection<E> raw) {
super(raw);
}
@Override
protected List<E> createEmpty() {
return Collections.emptyList();
}
@Override
protected List<E> copy(Collection<E> source) {
return new ArrayList<E>(source);
}
@Override
protected List<E> toUnmodifiable(List<E> source) {
return Collections.unmodifiableList(source);
}
}
public class ImmutableListTest {
@Test
public void testDefensiveCopyInput() {
List<Integer> in = new ArrayList<Integer>();
in.add(0);
ImmutableList<Integer> target = new ImmutableList<Integer>(in);
in.add(1);
Iterator<Integer> it = target.iterator();
assertThat(it.next(), is(0));
assertFalse(it.hasNext());
}
@Test
public void testDefensiveCopyOutput() {
ImmutableList<Integer> target = new ImmutableList<Integer>(Arrays.asList(0));
List<Integer> out = target.toRaw();
out.add(1);
Iterator<Integer> it = target.iterator();
assertThat(it.next(), is(0));
assertFalse(it.hasNext());
}
@Test
public void testSize() {
assertThat(new ImmutableList<Integer>(null).size(), is(0));
assertThat(new ImmutableList<Integer>(Arrays.asList(1, 2)).size(), is(2));
}
@Test
public void testIsEmpty() {
assertTrue(new ImmutableList<Integer>(null).isEmpty());
assertFalse(new ImmutableList<Integer>(Arrays.asList(1)).isEmpty());
}
@Test
public void testContains() {
ImmutableList<String> target = new ImmutableList<String>(Arrays.asList("a", "b"));
assertTrue(target.contains("a"));
assertFalse(target.contains("c"));
}
@Test
public void testIs() {
assertTrue(
new ImmutableList<String>(Arrays.asList("a", "b")).is(
new ImmutableList<String>(Arrays.asList("a", "b"))));
assertFalse(
new ImmutableList<String>(Arrays.asList("a", "b")).is(
new ImmutableList<String>(Arrays.asList("a", "c"))));
assertTrue(
new ImmutableList<String>(null).is(
new ImmutableList<String>(new ArrayList<String>())));
assertFalse(
new ImmutableList<String>(null).is(null));
}
@Test
public void testToString() {
assertThat(new ImmutableList<String>(Arrays.asList("a", "b")).toString(), is("[a, b]"));
assertThat(new ImmutableList<String>(null).toString(), is("[]"));
}
}
@froop
Copy link
Author

froop commented Apr 9, 2014

Google Guava の Immutable collections を使おう(提案)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment