将元素从"stream in stream"映射到集



我是Java流新手。

我有一个包含n个类的数组。

类有几个带有特定注释的字段(SomeAnnotationClass.class)

我试图得到一组所有的字段注释值,这是用这个特定的注释注释。如果字段没有注释,我想要字段的名称。

所以我试着这样做:

Stream.of(clazzes).map( c ->
Stream.of((c.getDeclaredFields()))
.map(
field ->
Optional.ofNullable(
field.getDeclaredAnnotation(SomeAnnotationClass.class).value())
.orElse(field.getName())).collect(Collectors.toSet())).collect(Collectors.toSet());

有两个问题:

  1. 我得到一个Set
  2. 如果注释不存在,我得到一个空指针,但SomeAnnotationClass.class.value()被称为

我可以用流优雅地实现这一点吗?

一组集合应该被平行化:

// in Main.java
public static Set<String> getValuesOrNames(Class ... clazzes) {
return Arrays.stream(clazzes)  // convert array to Stream<Class>
.flatMap(c -> Arrays.stream(c.getDeclaredFields())) // convert array of fields Stream<Field>
.map(field -> Optional.ofNullable(field.getAnnotation(SomeAnnotationClass.class))
.map(SomeAnnotationClass::value) // assuming SomeAnnotationClass has value method
.orElse(field.getName())
)
.collect(Collectors.toSet());
}

测试
// annotation class
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeAnnotationClass {
String value() default "";
}
import java.util.*;
import java.util.stream.Collectors;
import lombok.Data;
public class Main {
public static void main(String[] args) {
System.out.println(getValuesOrNames(Something.class, Main.class));
}
@Data
public static class Something {
@SomeAnnotationClass(value = "String foo")
private String foo;
@SomeAnnotationClass
private String emptyFoo;
private String bar;
@SomeAnnotationClass(value = "int id")
private int id;
}
}

输出
[, String foo, bar, int id]

正如@Andy Turner所提到的,您可以使用toflatMap将多个流映射到单个流,并避免在访问value()之前检查NPE的注释

Set<String> value = clazzes.stream().map(c -> Stream.of((c.getDeclaredFields()))
.map(field -> Optional.ofNullable(
field.getDeclaredAnnotation(SomeAnnotationClass.class)).map(SomeAnnotationClass::value).orElseGet(field::getName)).collect(Collectors.toSet()))
.flatMap(Collection::stream).collect(Collectors.toSet());
package io.falcon.instagram.indexer.util;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.Enumerated;
import javax.persistence.Id;
public class Example {
public static void main(String[] args) {
List<Class<?>> classes = List.of(Test.class);

Class<Enumerated> someAnnotationClass = Enumerated.class;

Set<String> fieldNames = 
classes.stream()
.flatMap(c -> Arrays.stream(c.getDeclaredFields().clone())) // because getDeclaredFields returns array type
.map((Field field) -> Optional.ofNullable(field.getDeclaredAnnotation(someAnnotationClass)).map(a -> field.getName()))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toSet());

System.out.println(fieldNames);
}

public static class Test {
@Id
private final String id;
@Id
@Enumerated
private final String field;
@Enumerated
private final String another;
@Enumerated
private final String theGame;
public Test(String id, String field, String another, String theGame) {
this.id = id;
this.field = field;
this.another = another;
this.theGame = theGame;
}
}
}

相关内容

  • 没有找到相关文章

最新更新