2015-03-25 47 views
4

我想根据条件返回一个流的值。只有以下面作为一个例子,在这里我要地图的任何苹果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); 
    } 
} 

我怎么能包括流三元条件?

+3

更多讨论,那么你可以使用'map'里面的条件。 – 2015-03-25 12:54:16

+0

@AlexisC。好的,谢谢,你可能是指'.map(type - > ArrayUtils.contains(APPLES,type)?APPLE:type)'?如果是这样,如果这是最好的解决方案,你可以添加它作为答案。 – membersound 2015-03-25 12:56:31

+1

而私人静态final HashSet APPLES = new HashSet <>(Arrays.asList(“apple”,“apple2”,“apple3”));''''和'public static Food fromValue(String value){ 返回APPLES.contains(value.toLowerCase())? APPLE:null; }'?时间复杂,编写代码少。 – 2015-03-25 13:03:34

回答

3

你可以做这样的:

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()); 
    } 
} 

在地图上查找会O(1)

+2

您不需要'getOrDefault'来获取空值。如果没有映射,您可以简单地调用'get()',因为它是普通'Map.get'方法的合约,返回'null'。顺便说一句。对于ASCII字符使用小写字母可能已足够,但对于不区分大小写的比较而言不是一个通用解决方案。 – Holger 2015-03-25 14:47:52

+1

@Holger啊是的,这是真的,我的头脑在哪里?让我编辑它。 – 2015-03-25 14:50:28

2

正如亚历克西斯建议,您可以使用地图操作

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

没有什么特别的三元运算符。所以,你可以在此映射操作只需添加到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替代它会执行不区分大小写的查找。

0

正如其他人所建议的,使用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()方法staticAPPLESEnumSet。虽然我意识到这个答案与@ Holger的非常相似,但我只是想展示另一种构建地图的方法。

2

根据以前的答案,特别是来自@Alexis,我编写了一些代码来检查展台方法(从Java 7和Java 8)。也许这对于Java 8上的新用户可能是有用的。

因此,我对原始答案进行了一些更改。首先,我把一些单元测试,我加了两个包装方法verifyNames()包含()。其次,当意外发生时的行动,我们可以使用一个默认行为,在这种情况下,当appleApproachTwo.fromValueJava8()被称为与不存在枚举值。

最后,最后一次更改使用java.util.Optional对象的潜在用途。在这种情况下,我们可以保护环境因与空对象不一致而崩溃。大约有默认值,可选和否则容易()方法Default Values and Actions

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); 
    } 
}