diff --git a/src/main/java/org/cactoos/list/Joined.java b/src/main/java/org/cactoos/list/Joined.java index e5b279b944..7a61394210 100644 --- a/src/main/java/org/cactoos/list/Joined.java +++ b/src/main/java/org/cactoos/list/Joined.java @@ -23,6 +23,7 @@ */ package org.cactoos.list; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -53,9 +54,11 @@ public Joined(final List... src) { * @param src Source lists */ public Joined(final Iterable> src) { - super(() -> new ListOf<>(src).stream() - .flatMap(List::stream) - .collect(Collectors.toList()) + super(() -> Collections.unmodifiableList( + new ListOf<>(src).stream() + .flatMap(List::stream) + .collect(Collectors.toList()) + ) ); } diff --git a/src/main/java/org/cactoos/list/StickyList.java b/src/main/java/org/cactoos/list/StickyList.java index 640418e0b4..8d41e4a3d9 100644 --- a/src/main/java/org/cactoos/list/StickyList.java +++ b/src/main/java/org/cactoos/list/StickyList.java @@ -24,13 +24,12 @@ package org.cactoos.list; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.ListIterator; import org.cactoos.iterable.IterableOf; import org.cactoos.scalar.StickyScalar; -import org.cactoos.scalar.UncheckedScalar; /** * List decorator that goes through the list only once. @@ -44,13 +43,7 @@ * @param Type of item * @since 0.8 */ -@SuppressWarnings("PMD.TooManyMethods") -public final class StickyList implements List { - - /** - * The gate. - */ - private final UncheckedScalar> gate; +public final class StickyList extends ListEnvelope { /** * Ctor. @@ -83,151 +76,15 @@ public StickyList(final Iterator items) { * @param list The iterable */ public StickyList(final Collection list) { - this.gate = new UncheckedScalar<>( + super( new StickyScalar<>( () -> { final List temp = new LinkedList<>(); temp.addAll(list); - return temp; + return Collections.unmodifiableList(temp); } ) ); } - @Override - public int size() { - return this.gate.value().size(); - } - - @Override - public boolean isEmpty() { - return this.gate.value().isEmpty(); - } - - @Override - public boolean contains(final Object object) { - return this.gate.value().contains(object); - } - - @Override - public Iterator iterator() { - return this.gate.value().iterator(); - } - - @Override - public Object[] toArray() { - return this.gate.value().toArray(); - } - - @Override - @SuppressWarnings("PMD.UseVarargs") - public Y[] toArray(final Y[] array) { - return this.gate.value().toArray(array); - } - - @Override - public boolean add(final X element) { - throw new UnsupportedOperationException( - "#add(final T element) is not supported" - ); - } - - @Override - public boolean remove(final Object object) { - throw new UnsupportedOperationException( - "#remove(final Object object) is not supported" - ); - } - - @Override - public boolean containsAll(final Collection collection) { - return this.gate.value().containsAll(collection); - } - - @Override - public boolean addAll(final Collection collection) { - throw new UnsupportedOperationException( - "#addAll(final Collection collection) is not supported" - ); - } - - @Override - public boolean addAll(final int index, - final Collection collection) { - throw new UnsupportedOperationException( - "#addAll() is not supported" - ); - } - - @Override - public boolean removeAll(final Collection collection) { - throw new UnsupportedOperationException( - "#removeAll(final Collection collection) is not supported" - ); - } - - @Override - public boolean retainAll(final Collection collection) { - throw new UnsupportedOperationException( - "#retainAll(final Collection collection) is not supported" - ); - } - - @Override - public void clear() { - throw new UnsupportedOperationException( - "#clear() is not supported" - ); - } - - @Override - public X get(final int index) { - return this.gate.value().get(index); - } - - @Override - public X set(final int index, final X element) { - throw new UnsupportedOperationException( - "#set() is not supported" - ); - } - - @Override - public void add(final int index, final X element) { - throw new UnsupportedOperationException( - "#add(final int index, final T element) is not supported" - ); - } - - @Override - public X remove(final int index) { - throw new UnsupportedOperationException( - "#remove(final int index) is not supported" - ); - } - - @Override - public int indexOf(final Object object) { - return this.gate.value().indexOf(object); - } - - @Override - public int lastIndexOf(final Object object) { - return this.gate.value().lastIndexOf(object); - } - - @Override - public ListIterator listIterator() { - return this.gate.value().listIterator(); - } - - @Override - public ListIterator listIterator(final int index) { - return this.gate.value().listIterator(index); - } - - @Override - public List subList(final int fromindex, final int toindex) { - return this.gate.value().subList(fromindex, toindex); - } } diff --git a/src/main/java/org/cactoos/map/MapOf.java b/src/main/java/org/cactoos/map/MapOf.java index ce455523af..e1b04a0ddd 100644 --- a/src/main/java/org/cactoos/map/MapOf.java +++ b/src/main/java/org/cactoos/map/MapOf.java @@ -23,6 +23,7 @@ */ package org.cactoos.map; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -163,7 +164,7 @@ public MapOf(final Iterable> entries) { for (final Map.Entry entry : entries) { temp.put(entry.getKey(), entry.getValue()); } - return temp; + return Collections.unmodifiableMap(temp); }); } diff --git a/src/main/java/org/cactoos/map/StickyMap.java b/src/main/java/org/cactoos/map/StickyMap.java index 993748bc27..9b43d3b7ec 100644 --- a/src/main/java/org/cactoos/map/StickyMap.java +++ b/src/main/java/org/cactoos/map/StickyMap.java @@ -23,6 +23,7 @@ */ package org.cactoos.map; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -161,7 +162,7 @@ public StickyMap(final Map map) { () -> { final Map temp = new HashMap<>(0); temp.putAll(map); - return temp; + return Collections.unmodifiableMap(temp); } ) ); diff --git a/src/main/java/org/cactoos/map/SyncMap.java b/src/main/java/org/cactoos/map/SyncMap.java new file mode 100644 index 0000000000..e96ff174f5 --- /dev/null +++ b/src/main/java/org/cactoos/map/SyncMap.java @@ -0,0 +1,164 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.cactoos.map; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.cactoos.Func; +import org.cactoos.iterable.IterableOf; +import org.cactoos.iterable.Mapped; +import org.cactoos.scalar.SyncScalar; + +/** + * Map decorator that goes through the map only once. + * + *

The map is read-only.

+ * + *

There is no thread-safety guarantee. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @param Type of key + * @param Type of value + * @since 0.24 + */ +public final class SyncMap extends MapEnvelope { + + /** + * Ctor. + * @param list List of entries + */ + @SafeVarargs + public SyncMap(final Map.Entry... list) { + this(new IterableOf<>(list)); + } + + /** + * Ctor. + * @param map The map to extend + * @param list List of entries + */ + @SafeVarargs + public SyncMap(final Map map, final Map.Entry... list) { + this(map, new IterableOf<>(list)); + } + + /** + * Ctor. + * @param map The map to extend + * @param list List of items + * @param key Func to create key + * @param value Func to create value + * @param Type of items in the list + * @checkstyle ParameterNumberCheck (5 lines) + */ + public SyncMap(final Map map, + final Iterable list, final Func key, + final Func value) { + this( + map, list, + item -> new MapEntry<>(key.apply(item), value.apply(item)) + ); + } + + /** + * Ctor. + * @param list List of items + * @param key Func to create key + * @param value Func to create value + * @param Type of items in the list + */ + public SyncMap(final Iterable list, final Func key, + final Func value) { + this(list, item -> new MapEntry<>(key.apply(item), value.apply(item))); + } + + /** + * Ctor. + * @param list List of items + * @param entry Func to create entry + * @param Type of items in the list + */ + public SyncMap(final Iterable list, + final Func> entry) { + this(new Mapped<>(entry, list)); + } + + /** + * Ctor. + * @param map The map to extend + * @param list List of items + * @param entry Func to create entry + * @param Type of items in the list + */ + public SyncMap(final Map map, final Iterable list, + final Func> entry) { + this(map, new Mapped<>(entry, list)); + } + + /** + * Ctor. + * @param list Entries for the entries + */ + public SyncMap(final Iterable> list) { + this(new MapOf<>(list)); + } + + /** + * Ctor. + * @param list Entries for the entries + */ + public SyncMap(final Iterator> list) { + this(() -> list); + } + + /** + * Ctor. + * @param map Pre-existing map we want to extend + * @param list Entries for the entries + */ + public SyncMap(final Map map, + final Iterable> list) { + this(new MapOf<>(map, list)); + } + + /** + * Ctor. + * @param map The map + */ + public SyncMap(final Map map) { + super( + new SyncScalar<>( + () -> { + final Map temp = new HashMap<>(0); + temp.putAll(map); + return Collections.unmodifiableMap(temp); + } + ) + ); + } + +} diff --git a/src/test/java/org/cactoos/map/SyncMapTest.java b/src/test/java/org/cactoos/map/SyncMapTest.java new file mode 100644 index 0000000000..e3f792bd90 --- /dev/null +++ b/src/test/java/org/cactoos/map/SyncMapTest.java @@ -0,0 +1,52 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.cactoos.map; + +import org.hamcrest.MatcherAssert; +import org.junit.Test; + +/** + * Test case for {@link StickyMap}. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 0.24 + * @checkstyle JavadocMethodCheck (500 lines) + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +public final class SyncMapTest { + + @Test + public void behavesAsMap() { + MatcherAssert.assertThat( + "Can't behave as a map", + new SyncMap( + new MapEntry<>(0, -1), + new MapEntry<>(1, 1) + ), + new BehavesAsMap<>(0, 1) + ); + } + +}