How to return a value by ternary condition in a stream?

I want to return the value of a stream based on a condition. Take just an example where I want to map any apple to Food.APPLE:

public enum Food {
    APPLE, APPLE2, APPLE3, BANANA, PINEAPPLE, CUCUMBER;

    private static final Food[] APPLES = new Food[] {APPLE, APPLE2, APPLE3};

    //java7
    public Food fromValue(String value) {
        for (Food type : Food.values()) {
            if (type.name().equalsIgnoreCase(value)) {
                return ArrayUtils.contains(APPLES, type) ? APPLE : type;
            }
        }
        return null;
    }

    //java8: how to include the array check for APPLES?
    public Food fromValue(String value) {
        return Arrays.stream(Food.values()).
            filter(type -> type.name().equalsIgnoreCase(value))
            .findFirst()
            .orElse(null);
    }
}

How to include a triple condition in a stream?

+4
source share
5 answers

You can do it as follows:

import static java.util.AbstractMap.SimpleImmutableEntry;

...

enum Food {
    APPLE, APPLE2, APPLE3, BANANA, PINEAPPLE, CUCUMBER;

    private static final Map<String, Food> MAP = Stream.concat(
                Stream.of(APPLE, APPLE2, APPLE3).map(e -> new SimpleImmutableEntry<>(e.name().toLowerCase(), APPLE)),
                Stream.of(BANANA, PINEAPPLE, CUCUMBER).map(e -> new SimpleImmutableEntry<>(e.name().toLowerCase(), e)))
            .collect(toMap(SimpleImmutableEntry::getKey, SimpleImmutableEntry::getValue));

    public static Food fromValue(String value) {
        return MAP.get(value.toLowerCase());
    }
}

Search on the map will be O(1).

+3
source

As Alexis suggested, you can use the card operation

public Food fromValue_v8(String value) {
    return Arrays.stream(Food.values())
        .filter(type-> type.name().equalsIgnoreCase(value))
        .map(type -> ArrayUtils.contains(APPLES, type) ? APPLE : type)
        .findFirst()
        .orElse(null);
}
+2
source

. Stream

public Food fromValue(String value) {
    return Arrays.stream(Food.values())
        .filter(type -> type.name().equalsIgnoreCase(value))
        .map(type -> ArrayUtils.contains(APPLES, type)? APPLE: type)
        .findFirst()
        .orElse(null);
}

. Map:

public enum Food {
    APPLE, APPLE2, APPLE3, BANANA, PINEAPPLE, CUCUMBER;

    private static final Map<String,Food> MAP
        = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    static {
       EnumSet<Food> apples=EnumSet.of(APPLE, APPLE2, APPLE3);
       apples.forEach(apple->MAP.put(apple.name(), APPLE));
       EnumSet.complementOf(apples).forEach(e->MAP.put(e.name(), e));
    }
    public static Food fromValue(String value) {
        return MAP.get(value);
    }
}

, APPLE , .

+2

, @Alexis, ( Java 7 Java 8). , Java 8.

, . , unit test, verifyNames() (). -, , , , appleApproachTwo.fromValueJava8() null .

, java.util.Optional. - . " " "" Default Values, Optional orElse()

    public enum Food {
    APPLE, APPLE2, APPLE3, BANANA, PINEAPPLE, CUCUMBER, NONE;

    private static final Food[] APPLES = new Food[] {APPLE, APPLE2, APPLE3};

    // approach one
    // java7: conventional use
    public Food fromValueJava7(String value) {
        for (Food type : Food.values()) {
            if (verifyNames(type, value)) {
                return contains(Food.APPLES, type) ? Food.APPLE : type;
            }
        }
        return null;
    }


    // approach two
    // java8: how to include the array check for APPLES?
    public Food fromValueJava8(String value) {
        return Arrays.stream(Food.values())
                .filter(type-> verifyNames(type, value))
                .map(type -> contains(Food.APPLES, type) ? Food.APPLE : type)
                .findFirst()
                .orElse(Food.NONE);
    }

    private boolean contains(Food[] apples, Food type) {
        return ArrayUtils.contains(apples, type);
    }

    private boolean verifyNames(Food type,String other) {
        return type.name().equalsIgnoreCase(other);
    }
    }

    //   FoodTest
    //   
    public class FoodTest {
    @Test
    public void foodTest(){
        Food appleApproachOne  = Food.APPLE;

        // from approach one
        assertEquals( appleApproachOne.fromValueJava7("APPLE"),   Food.APPLE);
        assertEquals( appleApproachOne.fromValueJava7("APPLE2"),  Food.APPLE);
        assertEquals( appleApproachOne.fromValueJava7("APPLE3"),  Food.APPLE);
        assertEquals( appleApproachOne.fromValueJava7("apple3"),  Food.APPLE);
        assertNull  ( appleApproachOne.fromValueJava7("apple4") );
        assertNull  ( appleApproachOne.fromValueJava7(null) );

        Food appleApproachTwo  = Food.APPLE;

        //from approach two
        assertEquals( appleApproachTwo.fromValueJava8("APPLE"),   Food.APPLE);
        assertEquals( appleApproachTwo.fromValueJava8("APPLE2"),  Food.APPLE);
        assertEquals( appleApproachTwo.fromValueJava8("APPLE3"),  Food.APPLE);
        assertEquals( appleApproachTwo.fromValueJava8("apple3"),  Food.APPLE);
        assertEquals( appleApproachOne.fromValueJava8("apple4"),  Food.NONE);
        assertEquals( appleApproachTwo.fromValueJava8(null),      Food.NONE);
    }
}
+2

, Map:

import java.util.EnumSet;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TernaryCondition {

    public enum Food {
        APPLE, APPLE2, APPLE3, BANANA, PINEAPPLE, CUCUMBER;

        private static final EnumSet<Food> APPLES = EnumSet.of(APPLE, APPLE2, APPLE3);

        private static final Map<String, Food> MAP = Stream.of(
            Food.values()).collect(
            Collectors.toMap(
                f -> f.name().toLowerCase(), 
                f -> APPLES.contains(f) ? APPLE : f));

        public static Food fromValue(String value) {
            return MAP.get(value.toLowerCase());
        }
    }

    public static void main(String[] args) {
        Food f = Food.fromValue("apple2");

        System.out.println(f); // APPLE
    }
}

fromValue() static APPLES a EnumSet. , @Holger's, .

0

All Articles