2015-06-12 81 views
2

功能性的方式下面是我试图转换成函数式编程代码一些必要的代码:积累对在java8

public class Person { 
    String name; 
    Token token; 

    public Person(String name, Token token) { 
     this.name = name; 
     this.token = token; 
    } 
} 
public class Token { 
    String id; 
    boolean isValid; 
    public Token(String id, boolean isValid) { 
     this.id = id; 
     this.isValid = isValid; 
    } 
    public String getId() { return id; } 
    public boolean isValid() {return isValid;} 
} 
public static List<Token> getTokensForPerson(String name) {...} 


public static List<Person> getPeople1 (String[] names) { 

    List<Person> people = new ArrayList<Person>(); 
    for (String name: names) { 
     List<Token> tokens = getTokensForPerson(name); 
     for (Token token: tokens) { 
      if (token.isValid()) { 
       people.add(new Person(name, token)); 
      } 
     } 

    } 
    return people; 
} 

这是我尝试做了功能性的方式。

public static List<Person> getPeople2 (String[] names) { 

    return Arrays.stream(names).map(name -> getTokensForPerson(name)) 
     .flatMap(tokens -> tokens.stream().filter(token -> token.isValid)) 
     .map(token -> new Person(name, token)) // <== compiler error here. "Cannot resolve symbol 'name'" 
     .collect(Collectors.toList()); 
} 

但是它不会编译,因为在过去的地图操作我需要参考name创建Person对象,name不可在那个时候。有任何想法吗?

+0

的 “当务之急” 是更好:) – ZhongYu

回答

2

可以移动map步骤flatMap内:

return Arrays.stream(names) 
     .<Person>flatMap(
       name -> getTokensForPerson(name).stream() 
         .filter(Token::isValid) 
         .map(token -> new Person(name, token))) 
     .collect(Collectors.toList()); 

这样,您就可以访问name变量为好。

StreamEx为基础的解决方案是较短的,但它需要第三方库:

return StreamEx.of(names) 
       .cross(name -> getTokensForPerson(name).stream()) 
       // Here we have the stream of entries 
       // where keys are names and values are tokens 
       .filterValues(Token::isValid) 
       .mapKeyValue(Person::new) 
       .toList(); 
0

有没有可能创造TokenExtended类扩展令牌,并添加名称,并从getTokensForPerson,而不是返回List<TokenExtended>List<Token>

public class TokenExtended extends Token { 
    private String name; 
    public TokenExtended(String name, String id, boolean isValid) { 
     super(id, isValid); 
     this.name = name; 
    } 
} 

这样,你的代码将工作

Arrays.stream(names).map(name -> getTokensForPerson(name)).flatMap(tokens -> tokens.stream().filter(token -> token.isValid)) 
      .map(token -> new Person(token.name, token)).collect(Collectors.toList());