希望有人能解决这个问题。
对象结构我有一个类似于
的对象结构主要对象是学生,学生获得一些信件
public class LetterRange {
private Date letterStartDate;
private Date letterEndDate;
public Date getLetterStartDate() {
return letterStartDate;
}
public void setLetterStartDate(Date letterStartDate) {
this.letterStartDate = letterStartDate;
}
public Date getLetterEndDate() {
return letterEndDate;
}
public void setLetterEndDate(Date letterEndDate) {
this.letterEndDate = letterEndDate;
}
}
public class Letters {
private String letterName;
private Set<LetterRange> letterRangeSet;
public String getLetterName() {
return letterName;
}
public void setLetterName(String letterName) {
this.letterName = letterName;
}
public Set<LetterRange> getLetterRangeSet() {
return letterRangeSet;
}
public void setLetterRangeSet(Set<LetterRange> letterRangeSet) {
this.letterRangeSet = letterRangeSet;
}
}
public class Student {
private String name;
Set<Letters> lettersSet;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Letters> getLettersSet() {
return lettersSet;
}
public void setLettersSet(Set<Letters> lettersSet) {
this.lettersSet = lettersSet;
}
}
public class StudentRunner {
public static void main(String args[]){
List<Student> studentList = new ArrayList<>();
Student one = new Student();
Student two= new Student();
Student three= new Student();
one.setName("John");
Letters johnLetter1 = new Letters();
johnLetter1.setLetterName("Kudos");
Letters janeLetter = new Letters();
janeLetter.setLetterName("Jane Kudos");
Letters otherJaneLetter = new Letters();
otherJaneLetter.setLetterName("Other Jane letter");
one.setLettersSet(new HashSet<Letters>() {{
add(johnLetter1);
add(janeLetter);
add(otherJaneLetter);
}});
two.setLettersSet(new HashSet<Letters>(){{
add(johnLetter1);
add(janeLetter);
}});
LetterRange johnLetter1Range = new LetterRange();
johnLetter1Range.setLetterStartDate(new Date());
johnLetter1Range.setLetterEndDate(new Date());
LetterRange johnLetter2Range = new LetterRange();
johnLetter1Range.setLetterStartDate(DateTime.now().plus(10).toDate());
johnLetter1Range.setLetterEndDate(DateTime.now().plus(10).toDate());
johnLetter1.setLetterRangeSet(new HashSet<LetterRange>() {{
add(johnLetter1Range);
add(johnLetter2Range);
}});
studentList.add(one);
Set dataSet = studentList.stream().flatMap(student -> student.getLettersSet().stream())
.collect(Collectors.toSet());
Letters dataMap= studentList.stream().flatMap(student -> student.getLettersSet().stream()).filter(letters -> StringUtils.contains(letters.getLetterName(),"Jane")).findAny().orElseThrow(
NoSuchElementException::new);
System.out.println(dataMap);
System.out.println(studentList.stream().flatMap(student -> student.getLettersSet().stream()).filter(letters -> StringUtils.contains(letters.getLetterName(),"Jane")).collect(Collectors.toSet()));
Assert.assertTrue(dataSet.size() == 1);
}
}
我试图让lambda根据过滤条件返回所有学生(最外面的对象列表)。我知道我们可以迭代旧的方式,但我想看看是否有一个lambda可以帮助我。 TIA。
答案 0 :(得分:6)
你需要的是2张平面地图:
Set<LetterRange> rangeOfLetters = studentList.stream()
.flatMap(x -> x.letterSet.stream())
.flatMap(x -> x.letterRanges.stream())
.collect(Collectors.toSet());
平面地图操作可以改变这一点:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
进入这个:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
您的数据结构如下:
[
<
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange}
>,
<
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange}
>,
<
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange}
>
]
[]
代表最外面的一组。 <>
表示学生对象,{}
表示字母对象。
第一张平面地图将数据转换为:
[
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange},
{LetterRange, LetterRange, LetterRange}
]
第二张平面地图将数据转换为:
[
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange,
LetterRange, LetterRange, LetterRange
]
答案 1 :(得分:4)
解决这个问题的方法是使用中间变量并查看每个阶段的结果。
Stream<Student> studentStream = studentList.stream();
......是一个好的开始。您可以自己选择studentStream
的类型,并且能够做到这一点很好。但是你的IDE会告诉你它是否错了 - 你甚至可以让IDE为你输入正确的类型。
您知道自己需要flatMap
,因为您知道自己正在展平嵌套结构。您传递给flatMap
的功能必须使用Student
并返回Stream<?>
,因此您的选项有限:
Stream<Letters> lettersStream = studentStream.flatMap(
stu -> stu.getLettersSet().stream());
从Stream<Letters>
接近你的目标与以前的思路基本相同:
Stream<LetterRange> letterRangeStream = lettersStream.flatMap(
ls -> ls.getLetterRangeSet().stream());
......现在你有你想要的东西;你只需要把它收集到List
:
List<LetterRange> letterRanges = letterRangeStream.collect(Collectors.toList());
您可以选择保留:
Stream<Student> studentStream = studentList.stream();
Stream<Letters> lettersStream = studentStream.flatMap(
stu -> stu.getLettersSet().stream());
Stream<LetterRange> letterRangeStream = lettersStream.flatMap(
ls -> ls.getLetterRangeSet().stream());
List<LetterRange> letterRanges = letterRangeStream.collect(Collectors.toList());
......这很好 - 无论如何,JRE将优化中间变量。但是,如果您愿意,可以将它们(通过手动,或使用IDE&#34;内联变量&#34;重构工具)内联到:
List<LetterRange> letterRanges = studentList.stream()
.flatMap(stu -> stu.getLettersSet().stream())
.flatMap(ls -> ls.getLetterRangeSet().stream())
.collect(Collectors.toList());