Skip to content

Commit

Permalink
Merge branch '__rultor'
Browse files Browse the repository at this point in the history
  • Loading branch information
rultor committed May 18, 2018
2 parents 01ff587 + 1ed8fe7 commit 7775a67
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/main/java/org/cactoos/collection/CollectionEnvelope.java
Expand Up @@ -36,6 +36,10 @@
*
* @param <X> Element type
* @since 0.23
* @todo #844:30min Implement methods equals and hashCode for this class.
* Implementation should rely on the items of the nested collection, but not
* on default JVM impl. Class {@link org.cactoos.map.MapEnvelope} can be used
* as an example.
* @checkstyle AbstractClassNameCheck (500 lines)
*/
@SuppressWarnings(
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/org/cactoos/map/MapEnvelope.java
Expand Up @@ -24,9 +24,12 @@
package org.cactoos.map;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.cactoos.Scalar;
import org.cactoos.scalar.Folded;
import org.cactoos.scalar.SumOfIntScalar;
import org.cactoos.scalar.UncheckedScalar;
import org.cactoos.text.TextOf;

Expand Down Expand Up @@ -138,4 +141,52 @@ public final String toString() {
.append('}')
.toString();
}

@Override
@SuppressWarnings("PMD.OnlyOneReturn")
public final boolean equals(final Object other) {
if (this == other) {
return true;
}
if (getClass() != other.getClass()) {
return false;
}
final MapEnvelope<?, ?> that = (MapEnvelope<?, ?>) other;
final Iterator<Entry<X, Y>> these =
this.map.value().entrySet().iterator();
final Iterator<? extends Entry<?, ?>> those =
that.map.value().entrySet().iterator();
while (these.hasNext() && those.hasNext()) {
final Entry<X, Y> first = these.next();
final Entry<?, ?> second = those.next();
if (!first.getKey().equals(second.getKey())) {
return false;
}
if (!first.getValue().equals(second.getValue())) {
return false;
}
}
return !these.hasNext() && !those.hasNext();
}

// @checkstyle MagicNumberCheck (30 lines)
@Override
public final int hashCode() {
return new UncheckedScalar<>(
new Folded<>(
42,
(hash, entry) -> {
final int keys = new SumOfIntScalar(
() -> 37 * hash,
() -> entry.getKey().hashCode()
).value();
return new SumOfIntScalar(
() -> 37 * keys,
() -> entry.getValue().hashCode()
).value();
},
this.map.value().entrySet()
)
).value();
}
}
107 changes: 107 additions & 0 deletions src/test/java/org/cactoos/map/MapEnvelopeTest.java
Expand Up @@ -27,6 +27,8 @@
import org.cactoos.func.FuncOf;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsNot;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
Expand All @@ -38,7 +40,9 @@
* @since 0.4
* @checkstyle JavadocMethodCheck (500 lines)
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
* @checkstyle DiamondOperatorCheck (500 lines)
*/
@SuppressWarnings("PMD.TooManyMethods")
public final class MapEnvelopeTest {

/**
Expand Down Expand Up @@ -203,4 +207,107 @@ public void mapContainsValueFalse() {
);
}

@Test
public void mapEqualsToItself() {
final MapOf<String, String> map =
new MapOf<String, String>(new MapEntry<>("key", "value"));
MatcherAssert.assertThat(
"Map doesn't equal to itself",
map,
new IsEqual<>(map)
);
}

@Test
public void mapNotEqualsToAnotherClass() {
final MapOf<String, String> map =
new MapOf<String, String>(new MapEntry<>("key1", "value1"));
MatcherAssert.assertThat(
"Map equals to an instance of another type",
map,
new IsNot<>(
new IsEqual<>("Totally different type")
)
);
}

@Test
public void mapEqualsToMapWithSameEntries() {
final String key = "key2";
final String value = "value2";
final MapEntry<String, String> input = new MapEntry<>(key, value);
final MapEntry<String, String> expected = new MapEntry<>(key, value);
MatcherAssert.assertThat(
"Map doesn't equal to another map with same entries",
new MapOf<String, String>(input),
new IsEqual<>(new MapOf<String, String>(expected))
);
}

@Test(expected = NullPointerException.class)
public void equalFailsOnNull() {
final MapEntry<String, String> first =
new MapEntry<>("key3", "value3");
final MapEntry<String, String> second =
new MapEntry<>("key4", null);
MatcherAssert.assertThat(
"Map allows null values, but shouldn't",
new MapOf<String, String>(first, second),
new IsEqual<>(new MapOf<String, String>(first, second))
);
}

@Test
public void mapNotEqualsToOtherWithDifferentKeys() {
final String value = "value5";
MatcherAssert.assertThat(
"Map equals to another map with different keys",
new MapOf<String, String>(new MapEntry<>("key5", value)),
new IsNot<>(
new IsEqual<>(
new MapOf<String, String>(
new MapEntry<>("key6", value)
)
)
)
);
}

@Test
public void mapNotEqualsToOtherWithDifferentValues() {
final String key = "key7";
MatcherAssert.assertThat(
"Map equals to another map with different values",
new MapOf<String, String>(new MapEntry<>(key, "value7")),
new IsNot<>(
new IsEqual<>(
new MapOf<String, String>(
new MapEntry<>(key, "value8")
)
)
)
);
}

@Test
public void hashCodeDependsOnItems() {
final String key = "key9";
final String value = "value9";
final MapEntry<String, String> input = new MapEntry<>(key, value);
final MapEntry<String, String> expected = new MapEntry<>(key, value);
MatcherAssert.assertThat(
"hashCode returns different results for same entries",
new MapOf<String, String>(input).hashCode(),
new IsEqual<>(new MapOf<String, String>(expected).hashCode())
);
}

@Test(expected = NullPointerException.class)
public void hashCodeFailsOnNull() {
final MapEntry<String, String> first =
new MapEntry<>("key10", "value10");
final MapEntry<String, String> second =
new MapEntry<>("key11", null);
new MapOf<String, String>(first, second).hashCode();
}
}

1 comment on commit 7775a67

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 7775a67 May 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 844-c2e67e6a discovered in src/main/java/org/cactoos/collection/CollectionEnvelope.java and submitted as #881. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.