如何使用筛选器将iterable更改为arraylist

ie3xauqp  于 2021-07-06  发布在  Java
关注(0)|答案(3)|浏览(376)

我有密码:

@GetMapping("/goal/{id}")
    public String goalInfo(@PathVariable(value = "id") long id, Model model) {

        if (!goalRepository.existsById(id)) {
            return "redirect:/goal";
        }

        Iterable<SubGoal> subGoal = subGoalRepository.findAll();
        ArrayList<SubGoal> subGoals = new ArrayList<>();

        //How refactor this?
        for(SubGoal sub : subGoal){
            if(sub.getParentGoal().getId().equals(id)){
                subGoals.add(sub);
            }
        }

        if(subGoals.size() > 0) {
            goalPercent(id, subGoal);
        }

        Optional<Goal> goal = goalRepository.findById(id);
        ArrayList<Goal> result = new ArrayList<>();
        goal.ifPresent(result::add);

        model.addAttribute("goal", result);
        model.addAttribute("subGoal",subGoals);
        return "goal/goal-info";
    }

在这里,我从存储库中获取子目标并过滤这些值。
没有foreach我怎么办?我想用溪流或者别的什么。

aij0ehis

aij0ehis1#

转换 IterableStream 使用 StreamSupport.stream(iter.spliterator(), par) .

Iterable<SubGoal> subGoal = subGoalRepository.findAll();

List<SubGoal> subGoals = StreamSupport
  .stream(subGoal.spliterator(), false)
  .filter(sub -> sub.getParentGoal().getId().equals(id))
  .collect(toList())  // static import `Collectors.toList()`

...

另外,这部分也可以是单语句。
前(三句话)

Optional<Goal> goal = goalRepository.findById(id);
ArrayList<Goal> result = new ArrayList<>();
goal.ifPresent(result::add);

后(单语句)

List<Goal> result = goalRepository.findById(id)
  .map(goal -> singletonList(goal)) // Collections.singletonList()
  .orElse(emptyList());             // Collections.emptyList()

更新

  1. singletonList() , emptyList() 这些只是创建单个实体列表和空列表时使用的工厂方法。
    你可以改变这部分的任何功能 Goal 作为输入和 List 作为输出和任何空列表。
    例如,
.map(goal -> Arrays.asList(goal)) 
.orElse(new ArrayList<>());

or 

.map(goal -> { 
  ArrayList<Goal> l = new ArrayList<>(); 
  l.add(goal);
  return l;
})
...

2.我将列表类型改为 List<Goal> ,不是 ArrayList<Goal> 对不起,我没听清楚。
在oop中,在许多情况下,使用接口比使用具体类更好。
如果你必须使用 ArrayList<> 显式键入或出于某种原因要指定实际的列表示例,也可以使用 toCollection() 就像下面一样。

.collect(toCollection(ArrayList::new)) // you can specify the actual list instance

感谢@john bollinger@hfontanez指出这一点。

mklgxw1f

mklgxw1f2#

这是客户端过滤,效率极低。相反,只需在存储库接口上声明此方法:

Collection<SubGoal> findByParentId(Long id); // or Stream, Iterable
gijlo24d

gijlo24d3#

不需要在代码中声明iterable来过滤arraylist。filter方法已经为您提供了一个。您可以使用:

subGoals = subGoals.stream().filter(subGoal ->
 /*Here goes your filter condition*/ ).collect(Collectors.toList());

相关问题