Java 使用优先级通过集合和筛选器进行流式处理
我正在尝试根据某个优先级筛选集合。 集合由具有特定类型字段的实体组成 因此,我想做以下几点: 对集合进行迭代/流式处理,并Java 使用优先级通过集合和筛选器进行流式处理,java,java-8,java-stream,Java,Java 8,Java Stream,我正在尝试根据某个优先级筛选集合。 集合由具有特定类型字段的实体组成 因此,我想做以下几点: 对集合进行迭代/流式处理,并 查找具有getType=“type1”的第一个实体。如果此实体的价格大于0,则返回此实体。否则 查找具有getType=“type2”的下一个实体。如果价格>0,则返回该价格。否则 查找具有getType=“type3”的下一个实体。如果价格>0,则返回该价格 查找具有getType=“type4”的下一个实体。如果价格>0,则返回该价格 查找具有getType=“
我正在尝试使用流进行此操作,但在筛选步骤中,我无法创建此优先级类型的筛选。我还尝试使用for循环遍历集合,但是不确定如何实现type1的
findFirst
实体,然后是type2等等。如果您稍微重新表述一下需求,它使流的一系列操作的转换更加清晰-您应该返回具有最小类型的price>0
的第一个项目:
MyEntity result = myList.stream()
.filter(e -> e.getPrice() > 0)
.min(Compartor.comparing(MyEntity::getType))
.orElse(null);
如果您稍微重新表述一下需求,它会使对流的一系列操作的转换更加清晰-您应该返回具有最小类型的price>0
的第一个项目:
MyEntity result = myList.stream()
.filter(e -> e.getPrice() > 0)
.min(Compartor.comparing(MyEntity::getType))
.orElse(null);
原始-无效的缩减方法
一个选项是翻转操作顺序。例如:在“price>0”处进行筛选,然后在遇到元素时减少流。例:
stream.filter(elem -> elem.price > 0)
.reduce((elem1, elem2) -> elem1.type.compareTo(elem2.type) < 0 ? elem1 : elem2)
stream.filter(elem->elem.price>0)
.reduce((elem1,elem2)->elem1.type.compareTo(elem2.type)<0?elem1:elem2)
编辑-更正确的缩减方法
通常,最好使流操作保持无状态。因此,创建一个处理遍历列表并返回结果的函数可能是更正确的方法。使用streams,可以定义一个自定义的“reducer”,它跟踪先前检查的类型,以确定下一个结果是否可能是有效匹配。一旦找到有效的匹配项,就会始终返回该匹配项
public static void main(String[] args)
{
List<Entity> data = Arrays.asList(eee(2, 6), eee(1, 0), eee(1, 10), eee(3, 7), eee(2, 0), eee(3, 5), eee(4, 0), eee(5, 0));
System.out.println(data.stream().reduce(new Reducer()).filter(entity -> entity != Reducer.NO_MATCH));
}
/*Once a match is found, always use it. For a given type, only the first found entity of that type will be used*/
public static final class Reducer implements BinaryOperator<Entity>
{
private int priorValidType;
Reducer(){ this.priorValidType = 0; }
@Override
public Entity apply(Entity result, Entity newElem)
{
int nextValidType = priorValidType + 1;
if(priorValidType > 0 && result != NO_MATCH) return result; /*Match already found, use it*/
if(result.type == nextValidType && result.price > 0) { priorValidType = nextValidType; return result; } /*result is a match*/
if(newElem.type == nextValidType && newElem.price > 0) { priorValidType = nextValidType; return newElem; } /*newElem is a match*/
if(result.type == nextValidType || newElem.type == nextValidType) { priorValidType = nextValidType; }
return NO_MATCH; /*No match has been found*/
}
public static final Entity NO_MATCH = new Entity(-1, -1);
}
public static final class Entity
{
private final int price, type;
Entity(int type, int price){ this.price = price; this.type = type; }
public String toString(){ return "(" + type + ", " + price + ")"; }
int getPrice(){ return price; }
int getType(){ return type; }
public static Entity eee(int type, int price){ return new Entity(type, price); }
}
publicstaticvoidmain(字符串[]args)
{
列表数据=数组.asList(eee(2,6),eee(1,0),eee(1,10),eee(3,7),eee(2,0),eee(3,5),eee(4,0),eee(5,0));
System.out.println(data.stream().reduce(new Reducer()).filter(entity->entity!=Reducer.NO_MATCH));
}
/*一旦找到匹配项,请始终使用它。对于给定类型,将仅使用该类型的第一个找到的实体*/
公共静态最终类缩减器实现BinaryOperator
{
私有int-priorValidType;
Reducer(){this.priorValidType=0;}
@凌驾
公共实体应用(实体结果、实体新元素)
{
int nextValidType=priorValidType+1;
如果(priorValidType>0&&result!=无匹配项)返回结果;/*已找到匹配项,请使用它*/
如果(result.type==nextValidType&&result.price>0){priorValidType=nextValidType;return result;}/*结果匹配*/
如果(newElem.type==nextValidType&&newElem.price>0){priorValidType=nextValidType;return newElem;}/*newElem是匹配项*/
如果(result.type==nextValidType | | newElem.type==nextValidType){priorValidType=nextValidType;}
return NO_MATCH;/*未找到匹配项*/
}
公共静态最终实体不匹配=新实体(-1,-1);
}
公共静态最终类实体
{
私人最终整数价格,类型;
实体(int-type,int-price){this.price=price;this.type=type;}
公共字符串toString(){return“(“+type+”,“+price+”);}
int getPrice(){返回价格;}
int getType(){return type;}
公共静态实体eee(int类型,int价格){返回新实体(类型,价格);}
}
编辑-使用过滤器的替代方法
可以创建一个过滤器,它执行类似于reduce方法的操作,并且在调用“findFirst”时具有短路的好处。在下面的示例中,第一个过滤器仅允许与给定类型(顺序)的第一次相遇通过。第二个过滤器确认它是有效的
public static void main(String[] args)
{
List<Entity> data = Arrays.asList(eee(2, 6), eee(1, 0), eee(1, 10), eee(3, 7), eee(2, 0), eee(3, 5), eee(4, 0), eee(5, 0));
System.out.println(data.stream().filter(new FirstTypeMatch()).filter(entity -> entity.price > 0).findFirst());
}
/*Filter where the element is the first of the given type*/
public static final class FirstTypeMatch implements Predicate<Entity>
{
private int priorValidType = 0;
@Override
public boolean test(Entity nextElem)
{
if(nextElem.type == (priorValidType + 1)){ priorValidType++; return true; }
return false;
}
}
publicstaticvoidmain(字符串[]args)
{
列表数据=数组.asList(eee(2,6),eee(1,0),eee(1,10),eee(3,7),eee(2,0),eee(3,5),eee(4,0),eee(5,0));
System.out.println(data.stream().filter(new FirstTypeMatch()).filter(entity->entity.price>0.findFirst());
}
/*元素是给定类型的第一个的过滤器*/
公共静态final类FirstTypeMatch实现谓词
{
private int priorValidType=0;
@凌驾
公共布尔测试(实体nextem)
{
if(nextElem.type==(priorValidType+1)){priorValidType++;返回true;}
返回false;
}
}
原始-无效还原方法
一个选项是翻转操作顺序。例如:在“price>0”处进行筛选,然后在遇到元素时减少流。例:
stream.filter(elem -> elem.price > 0)
.reduce((elem1, elem2) -> elem1.type.compareTo(elem2.type) < 0 ? elem1 : elem2)
stream.filter(elem->elem.price>0)
.reduce((elem1,elem2)->elem1.type.compareTo(elem2.type)<0?elem1:elem2)
编辑-更正确的缩减方法
通常,最好使流操作保持无状态。因此,创建一个处理遍历列表并返回结果的函数可能是更正确的方法。使用streams,可以定义一个自定义的“reducer”,它跟踪先前检查的类型,以确定下一个结果是否可能有效
MyClass selected = Arrays.stream(types)
.map(type -> list.stream()
.filter(obj -> obj.getType().equals(type))
.findFirst()
.orElse(null))
.filter(a -> a != null && a.getPrice() > 0)
.findFirst().orElse(new MyClass(-1, "Empty"));
System.out.println(selected);
[10, Type2]
Optional<Entity> entity = list.stream().sorted(Comparator.comparing(Entity::getType))
.filter( e -> e.price > 0 ).findFirst();
if(entity.isPresent()){
System.out.println(entity.get().getType()); // test to verify
}