Java 8 无法使用枚举筛选元素

Java 8 无法使用枚举筛选元素,java-8,enums,java-stream,Java 8,Enums,Java Stream,我将ComputerComponent类的列表传递给averagePrice()函数,该函数有两个price字段 是双重和双重的类型 类型为字符串的类别 我的列表有4个元素,分类为“CPU”、“鼠标”, “键盘”和“存储”,价格分别为34.0、155.0、23.0和75.0 当我尝试使用inEnum()、isInEnum()或EnumUtils.isValidEnum()函数时,我得到了平均价格 作为34.0,我认为他们只是返回第一个元素的价格,而不是平均值 protected static d

我将ComputerComponent类的列表传递给averagePrice()函数,该函数有两个price字段 是双重和双重的类型 类型为字符串的类别

我的列表有4个元素,分类为“CPU”、“鼠标”, “键盘”和“存储”,价格分别为34.0、155.0、23.0和75.0

当我尝试使用inEnum()、isInEnum()或EnumUtils.isValidEnum()函数时,我得到了平均价格 作为34.0,我认为他们只是返回第一个元素的价格,而不是平均值

protected static double averagePrice( List<ComputerComponent> list ) { 
    return  list.stream()
            //  .filter( line-> EnumUtils.isValidEnum(ComputerComponentCategory.class, line.getCategory()) )    

            //  .filter( line-> isInEnum( line.getCategory(), ComputerComponentCategory.class) )    
            //   .filter( line->  inEnum(line.getCategory(),EnumUtils.getEnumMap(ComputerComponentCategory.class ).keySet() ))  
                .filter(    line -> 
                        line.getCategory().contains("CPU")  
                        || line.getCategory().contains("GPU")
                        || line.getCategory().contains("Monitor")
                        || line.getCategory().contains("Keyboard")
                        || line.getCategory().contains("Mouse")
                        || line.getCategory().contains("Storage")
                        || line.getCategory().contains("Memory")) 
               .mapToDouble(ComputerComponent::getPrice)
               .average() 
               .orElseThrow(NoSuchElementException:: new); 
    }
我得到了正确的平均值71.75

我用于isInEnum()和inEnum()函数的实现如下:

But when I do filtering using 

                            .filter(    line -> 
                        line.getCategory().contains("CPU")  
                        || line.getCategory().contains("GPU")
                        || line.getCategory().contains("Monitor")
                        || line.getCategory().contains("Keyboard")
                        || line.getCategory().contains("Mouse")
                        || line.getCategory().contains("Storage")
                        || line.getCategory().contains("Memory"))
公共静态布尔值isInEnum(字符串值,类enumClass){
对于(E:enumClass.getEnumConstants()){
如果(e.name().contains(value)){return true;}
}
返回false;
}
公共静态布尔inEnum(字符串类别,设置值){
for(字符串s:值){
如果(类别包含){
返回true;
}
}
返回false;
}
如何在java streams中正确使用枚举来按有效的类别名称进行筛选并获得正确的 平均价格


使用streams及其函数时我犯了什么错误

您只需使用
ComputerCategoryValue.getValue方法,并根据
行的类别检查null:

public static <E extends Enum<E>> boolean isInEnum(String value, Class<E> enumClass) {
      for (E e : enumClass.getEnumConstants()) {
        if(e.name().contains(value)) { return true; }
      }
      return false;
    }


public static boolean inEnum ( String category, Set<String> value ) {   
    for(String s: value ) {
    if ( category.contains(s) ) {
        return true ;  
    }
    }
    return false ;
}
公共类枚举测试{
@试验
public void testBothMethods(){
最终的ComputerComponent c1=新的ComputerComponent(ComputerComponentCategory.CPU.getLabel(),12.21);
最终的ComputerComponent c2=新的ComputerComponent(ComputerComponentCategory.MEMORY.getLabel(),23.45);
最终列表=数组.asList(c1,c2);
assertEquals(带过滤器的平均价格(列表),带过滤器的平均价格(列表),0.01);
}
带筛选器的受保护静态双平均价格(最终列表){
return list.stream()
.filter(line->line.getCategory().contains(“CPU”)
||line.getCategory()包含(“GPU”)
||line.getCategory()包含(“监视器”)
||line.getCategory()包含(“键盘”)
||line.getCategory()包含(“鼠标”)
||line.getCategory()包含(“存储”)
||line.getCategory()包含(“内存”))
.mapToDouble(计算机组件::getPrice)
.average()
.orelsetrow(NoSuchElementException::new);
}
受保护的静态双平均价格WithInenum(最终列表){
return list.stream()
.filter(line->ComputerComponentCategory.getValue(line.getCategory())!=null)
.mapToDouble(计算机组件::getPrice)
.average()
.orelsetrow(NoSuchElementException::new);
}
}
编辑:解释你的错误:

  • EnumUtils.getEnumMap(ComputerComponentCategory.class).keySet())
    返回枚举名称的映射(而不是其
    标签
    ),因此检查仅适用于
    CPU
    ,因为名称和标签相同

  • 其他方法也一样


  • 您需要使用
    getLabel()
    而不是
    name()
    或使用
    equalsIgnoreCase
    而不是
    contains

    谢谢您的解释。你知道为什么EnumUtils.isValidEnum()不起作用吗?是的,同样的解释也适用<枚举的code>name
    基本上是常量的字符串表示形式,例如“MONITOR”。您的类别可能使用“Monitor”标签,这显然不同(大写)。您可以将标签
    转换为UpperCase
    ,但我强烈建议您只使用枚举提供的便捷方法,就像我的答案一样。也许更好:不要在ComputerComponent中使用category标签,只需将category属性键入为ComputerComponentCategory并直接使用枚举即可。
    public class EnumTest {
    
        @Test
        public void testBothMethods() {
            final ComputerComponent c1 = new ComputerComponent(ComputerComponentCategory.CPU.getLabel(), 12.21);
            final ComputerComponent c2 = new ComputerComponent(ComputerComponentCategory.MEMORY.getLabel(), 23.45);
            final List<ComputerComponent> list = Arrays.asList(c1, c2);
    
            assertEquals(averagePriceWithFilter(list), averagePriceWithInEnum(list), 0.01);
        }
    
        protected static double averagePriceWithFilter(final List<ComputerComponent> list) {
            return list.stream()
                    .filter(line -> line.getCategory().contains("CPU")
                            || line.getCategory().contains("GPU")
                            || line.getCategory().contains("Monitor")
                            || line.getCategory().contains("Keyboard")
                            || line.getCategory().contains("Mouse")
                            || line.getCategory().contains("Storage")
                            || line.getCategory().contains("Memory"))
                    .mapToDouble(ComputerComponent::getPrice)
                    .average()
                    .orElseThrow(NoSuchElementException::new);
        }
    
        protected static double averagePriceWithInEnum(final List<ComputerComponent> list) {
            return list.stream()
                    .filter(line -> ComputerComponentCategory.getValue(line.getCategory()) != null)
                    .mapToDouble(ComputerComponent::getPrice)
                    .average()
                    .orElseThrow(NoSuchElementException::new);
        }
    }