java-8 - 无法使用枚举过滤元素
问题描述
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);
}
我有一个枚举
public enum ComputerComponentCategory {
CPU("CPU"),
MONITOR("Monitor"),
KEYBOARD("Keyboard"),
MOUSE("Mouse"),
GPU("GPU"),
MEMORY("Memory"),
STORAGE("Storage"),
NULL("NOT DEFINED");
private String label;
ComputerComponentCategory(String label) {
this.label = label;
}
public String getLabel() {
return this.label;
}
public static ComputerComponentCategory getValue(String label) {
switch(label) {
case "CPU":
return CPU;
case "Monitor":
return MONITOR;
case "Keyboard":
return KEYBOARD;
case "Mouse":
return MOUSE;
case "GPU":
return GPU;
case "Memory":
return MEMORY;
case "Storage":
return STORAGE;
default:
return NULL ;
}
}
}
我将 ComputerComponent 类的列表传递给 averagePrice() 函数,该函数具有两个类型为 double 的价格字段和类型为 String 的类别。
我的列表有 4 个元素,类别为“CPU”、“鼠标”、“键盘”和“存储”,它们各自的价格分别为 34.0、155.0、23.0 和 75.0。
当我尝试使用 inEnum()、isInEnum() 或 EnumUtils.isValidEnum() 函数时,我得到的平均价格为 34.0,我认为它们只是返回第一个元素的价格而不是平均值。
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"))
我得到正确的平均值 71.75。
我用于 isInEnum() 和 inEnum() 函数的实现如下:
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 ;
}
如何正确使用枚举和 Java 流来按有效类别名称过滤并获得正确的平均价格?
使用流及其功能时我犯了什么错误?
解决方案
鉴于以下类别,您可以简单地使用您的ComputerCategoryValue.getValue
方法并检查 null line
:
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);
}
}
编辑:解释你的错误:
EnumUtils.getEnumMap(ComputerComponentCategory.class).keySet())
返回枚举名称(不是它的label
)的映射,以便检查仅适用于CPU
名称和标签相同的情况。其他方法也一样!
您需要使用getLabel()
代替name()
或使用equalsIgnoreCase
代替contains
。
推荐阅读
- google-apps-script - 使用 Google Apps 脚本获取工作表中包含特定列为空的数据的所有行
- docker - Windows 10 和 Docker 容器日志/Docker Logging 驱动程序
- json - 从字典值中收集特定项目并创建一个新字典
- excel - 我创建了一个 VBA excel 宏来查找重复值,如何改进我的代码?
- c++ - 如何使用 Qt 打印到网络热敏打印机
- image - 将图像恢复为原始图像
- excel - 如何使用excel数据透视表计算字段减去两次?
- vba - 无法使用 InsertCrossReference(导致运行时错误 4198)
- c - RISC-V 链接器抛出部分 LMA 重叠错误,尽管 LMA 属于不同的内存区域
- javascript - SVG 变形动画给出了非常奇怪的结果