diff --git a/src/main/java/org/cactoos/scalar/Folded.java b/src/main/java/org/cactoos/scalar/Folded.java index c093e145d2..e8b901b8ac 100644 --- a/src/main/java/org/cactoos/scalar/Folded.java +++ b/src/main/java/org/cactoos/scalar/Folded.java @@ -38,6 +38,28 @@ * ).value() // returns 10L * * + *

Here is how you can use it to + * find one of items according to the specified {@link BiFunc}:

+ * + *
+ *  final String apple = new Folded<>(
+ *          (first, last) -> first,
+ *          new IterableOf<Scalar<String>>(
+ *              () -> "Apple",
+ *              () -> "Banana",
+ *              () -> "Orange"
+ *          )
+ *      ).value();
+ *  final String orange = new Folded<>(
+ *          (first, last) -> last,
+ *          new IterableOf<Scalar<String>>(
+ *              () -> "Apple",
+ *              () -> "Banana",
+ *              () -> "Orange"
+ *          )
+ *      ).value();
+ * 
+ * *

There is no thread-safety guarantee. * *

This class implements {@link Scalar}, which throws a checked @@ -49,7 +71,7 @@ * @author Eduard Balovnev (bedward70@mail.ru) * @version $Id$ * @param Scalar type - * @since 0.9 + * @since 0.29 */ public final class Folded implements Scalar { diff --git a/src/main/java/org/cactoos/scalar/LowestOf.java b/src/main/java/org/cactoos/scalar/LowestOf.java new file mode 100644 index 0000000000..8f3d96ad71 --- /dev/null +++ b/src/main/java/org/cactoos/scalar/LowestOf.java @@ -0,0 +1,114 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017-2018 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.scalar; + +import org.cactoos.Scalar; +import org.cactoos.iterable.IterableOf; +import org.cactoos.iterable.Mapped; + +/** + * Find the lowest item. + * + *

Here is how you can use it to + * find lowest of {@link Comparable} items:

+ * + *
+ * final String lowest = new LowestOf<String>(
+ *         () -> "Banana", () -> "Apple", () -> "Orange"
+ *     ).value();
+ * // -> lowest == "Apple"
+ *
+ * final Character lowestChar = new LowestOf<>('B', 'U', 'G').value();
+ * // -> lowestChar == 'B'
+ * 
+ * + *

This class implements {@link Scalar}, which throws a checked + * {@link Exception}. This may not be convenient in many cases. To make + * it more convenient and get rid of the checked exception you can + * use {@link UncheckedScalar} or {@link IoCheckedScalar} decorators.

+ * + *

There is no thread-safety guarantee. + * + * @author Fabricio Cabral (fabriciofx@gmail.com) + * @author Eduard Balovnev (bedward70@mail.ru) + * @version $Id$ + * @param Scalar type + * @see UncheckedScalar + * @see IoCheckedScalar + * @since 0.29 + */ +public final class LowestOf> implements Scalar { + + /** + * Result. + */ + private final Scalar result; + + /** + * Ctor. + * @param items The comparable items + */ + @SafeVarargs + public LowestOf(final T... items) { + this( + new Mapped<>( + item -> () -> item, + items + ) + ); + } + + /** + * Ctor. + * @param scalars The scalars + */ + @SafeVarargs + public LowestOf(final Scalar... scalars) { + this(new IterableOf<>(scalars)); + } + + /** + * Ctor. + * @param iterable The items + */ + public LowestOf(final Iterable> iterable) { + this.result = new Folded<>( + (first, second) -> { + final T value; + if (first.compareTo(second) < 0) { + value = first; + } else { + value = second; + } + return value; + }, + iterable + ); + } + + @Override + public T value() throws Exception { + return this.result.value(); + } +} diff --git a/src/test/java/org/cactoos/scalar/FoldedTest.java b/src/test/java/org/cactoos/scalar/FoldedTest.java index 0796e8efc0..4574ab5f4a 100644 --- a/src/test/java/org/cactoos/scalar/FoldedTest.java +++ b/src/test/java/org/cactoos/scalar/FoldedTest.java @@ -36,7 +36,7 @@ * * @author Eduard Balovnev (bedward70@mail.ru) * @version $Id$ - * @since 1.0 + * @since 0.29 * @checkstyle JavadocMethodCheck (500 lines) */ public final class FoldedTest { @@ -46,8 +46,7 @@ public void failsForEmptyIterable() throws Exception { new Folded<>( (first, last) -> first, Collections.emptyList() - ) - .value(); + ).value(); } @Test diff --git a/src/test/java/org/cactoos/scalar/LowestOfTest.java b/src/test/java/org/cactoos/scalar/LowestOfTest.java new file mode 100644 index 0000000000..2781383736 --- /dev/null +++ b/src/test/java/org/cactoos/scalar/LowestOfTest.java @@ -0,0 +1,264 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017-2018 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.scalar; + +import java.util.Collections; +import java.util.Date; +import java.util.NoSuchElementException; +import org.cactoos.time.DateOf; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; + +/** + * Test case for {@link LowestOf}. + * + * @author Fabricio Cabral (fabriciofx@gmail.com) + * @author Eduard Balovnev (bedward70@mail.ru) + * @version $Id$ + * @since 0.29 + * @checkstyle JavadocMethodCheck (500 lines) + * @checkstyle MagicNumberCheck (500 lines) + */ +@SuppressWarnings("PMD.AvoidDuplicateLiterals") +public final class LowestOfTest { + + @Test(expected = NoSuchElementException.class) + public void failsForEmptyIterable() throws Exception { + new LowestOf<>(() -> Collections.emptyIterator()).value(); + } + + @Test + public void singleAtSingleIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest among one by scalars", + new LowestOf(() -> 10).value(), + Matchers.equalTo(10) + ); + MatcherAssert.assertThat( + "Can't find the lowest among one", + new LowestOf<>(10).value(), + Matchers.equalTo(10) + ); + } + + @Test + public void lowestIntegerAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest integer among many by scalars", + new LowestOf( + () -> 10, + () -> 0, + () -> -1, + () -> 2 + ).value(), + Matchers.equalTo(-1) + ); + MatcherAssert.assertThat( + "Can't find the lowest integer among many", + new LowestOf<>(10, 0, -1, 2).value(), + Matchers.equalTo(-1) + ); + MatcherAssert.assertThat( + "Can't find the lowest positive integer among many", + new LowestOf<>(272, 10, 134, 101).value(), + Matchers.equalTo(10) + ); + MatcherAssert.assertThat( + "Can't find the lowest negative integer among many", + new LowestOf<>(-272, -10, -134, -101).value(), + Matchers.equalTo(-272) + ); + MatcherAssert.assertThat( + "Can't find the lowest min integer among many", + new LowestOf<>(Integer.MIN_VALUE, Integer.MAX_VALUE).value(), + Matchers.equalTo(Integer.MIN_VALUE) + ); + } + + @Test + public void lowestLongAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest long among many by scalars", + new LowestOf( + () -> 10L, + () -> 0L, + () -> -1L, + () -> 2L + ).value(), + Matchers.equalTo(-1L) + ); + MatcherAssert.assertThat( + "Can't find the lowest long among many", + new LowestOf<>(10L, 0L, -1L, 2L).value(), + Matchers.equalTo(-1L) + ); + MatcherAssert.assertThat( + "Can't find the lowest positive long among many", + new LowestOf<>(272L, 10L, 134L, 101L).value(), + Matchers.equalTo(10L) + ); + MatcherAssert.assertThat( + "Can't find the lowest negative long among many", + new LowestOf<>(-272L, -10L, -134L, -101L).value(), + Matchers.equalTo(-272L) + ); + MatcherAssert.assertThat( + "Can't find the lowest mix integer long many", + new LowestOf<>(Long.MIN_VALUE, Long.MAX_VALUE).value(), + Matchers.equalTo(Long.MIN_VALUE) + ); + } + + @Test + public void lowestDoubleAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest double among many by scalars", + new LowestOf( + () -> 10.9, + () -> 0.8, + () -> -1.5, + () -> 10.8 + ).value(), + Matchers.equalTo(-1.5) + ); + MatcherAssert.assertThat( + "Can't find the lowest double among many", + new LowestOf<>(10., 0., -1., 2.).value(), + Matchers.equalTo(-1.) + ); + MatcherAssert.assertThat( + "Can't find the lowest positive double among many", + new LowestOf<>(272., 10., 134., 101.).value(), + Matchers.equalTo(10.) + ); + MatcherAssert.assertThat( + "Can't find the lowest negative double among many", + new LowestOf<>(-272., -10., -134., -101.).value(), + Matchers.equalTo(-272.) + ); + MatcherAssert.assertThat( + "Can't find the lowest mix double among many", + new LowestOf<>(Double.MIN_VALUE, Double.MAX_VALUE).value(), + Matchers.equalTo(Double.MIN_VALUE) + ); + MatcherAssert.assertThat( + "Can't find the lowest min double among many", + new LowestOf<>(Double.MIN_VALUE, 10.).value(), + Matchers.equalTo(Double.MIN_VALUE) + ); + MatcherAssert.assertThat( + "Can't find the lowest NaN (with min) double among many", + new LowestOf<>(Double.NaN, Double.MIN_VALUE).value(), + Matchers.equalTo(Double.MIN_VALUE) + ); + MatcherAssert.assertThat( + "Can't find the lowest NaN (with max) double among many", + new LowestOf<>(Double.NaN, Double.MAX_VALUE).value(), + Matchers.equalTo(Double.MAX_VALUE) + ); + MatcherAssert.assertThat( + "Can't find the lowest positive infinity among many", + new LowestOf<>(Double.POSITIVE_INFINITY, Double.MAX_VALUE).value(), + Matchers.equalTo(Double.MAX_VALUE) + ); + MatcherAssert.assertThat( + "Can't find the lowest negative infinity among many", + new LowestOf<>(Double.NEGATIVE_INFINITY, Double.MAX_VALUE).value(), + Matchers.equalTo(Double.NEGATIVE_INFINITY) + ); + } + + @Test + public void lowestStringAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest string among many by scalars", + new LowestOf( + () -> "Banana", + () -> "Apple", + () -> "Orange" + ).value(), + Matchers.equalTo("Apple") + ); + MatcherAssert.assertThat( + "Can't find the lowest string among many", + new LowestOf<>("Banana", "Apple", "Orange").value(), + Matchers.equalTo("Apple") + ); + } + + @Test + public void lowestCharAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest char among many by scalars", + new LowestOf(() -> 'B', () -> 'U', () -> 'G').value(), + Matchers.equalTo('B') + ); + MatcherAssert.assertThat( + "Can't find the lowest char among many", + new LowestOf<>('H', 'A', 'N', 'D').value(), + Matchers.equalTo('A') + ); + } + + @Test + public void lowestSumAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest double sum among many", + new LowestOf( + new SumOf(1.0d), + new SumOf(1.0d, 2.0d), + new SumOf(1.0d, 2.0d, 3.0d) + ).value(), + Matchers.equalTo(new SumOf(1.0d).value()) + ); + } + + @Test + public void lowestDateAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest date among many", + new LowestOf( + new DateOf("2007-12-26T14:20:16.000000016Z"), + new DateOf("2007-12-26T14:20:16.000000017Z"), + new DateOf("2011-10-01T14:15:16.000000017Z") + ).value(), + Matchers.equalTo( + new DateOf("2007-12-26T14:20:16.000000016Z").value() + ) + ); + } + + @Test + public void lowestBooleanAtIterable() throws Exception { + MatcherAssert.assertThat( + "Can't find the lowest boolean among many", + new LowestOf( + new BoolOf("false"), + new BoolOf("true") + ).value(), + Matchers.equalTo(new BoolOf("false").value()) + ); + } +}