【问题标题】:Create custom collector in java在java中创建自定义收集器
【发布时间】:2021-04-16 10:08:47
【问题描述】:

我有两个课程会议和访客。

关系如下:

class Meeting {

private LocalDate date;
private List<Guest> guests;

}

我需要使用流按日期和来自美国的客人的地点安排一次会议。

我有列表,我已经完成了下一个:

List<Meeting> meetings = new ArrayList<>();

public Meeting getByDay(LocalDate date) {
    List<Guest> guests = getGuestsByDate(date).stream()
            .filter(guest-> guest.getCountry().equals("USA"))
            .collect(Collectors.toList());
    return new Meeting(date, guests);
}

但现在我需要使用自定义收集器重构我的代码,它会返回会议。 我读到它需要实现 Collector 接口或 Collector.of() 方法,但在我的情况下它必须如何?如有任何建议,我将不胜感激。

【问题讨论】:

  • getGuestsByDate(date) 了解其实现会更有趣。
  • .collect(Collectors.toList()).collect(Collectors.collectingAndThen(Collectors.toList(), l-&gt;new Meeting(date,l)))

标签: java java-stream collectors


【解决方案1】:

我不推荐这种方式,但如果需要,可以使用:

    Meeting m = Stream.of(new Guest(), new Guest())
        .collect(Collector.of(
            () -> new Meeting(date),
            Meeting::addGuest,
            (m1, m2) -> {
              ArrayList<Guest> guestsAll = new ArrayList<>(m1.getGuests());
              guestsAll.addAll(m2.getGuests());
              return new Meeting(date, guestsAll);
            }
        ));

我在Meeting 类中添加了几个构造函数和方法

    Meeting(LocalDate date) {
      this.date = date;
      this.guests = new ArrayList<>();
    }

    Meeting(LocalDate date, List<Guest> guests) {
      this.date = date;
      this.guests = guests;
    }

    public void addGuest(Guest g) {
      guests.add(g);
    }

【讨论】:

    【解决方案2】:

    虽然问题是关于使用Collector,但您也可以使用reduce 运算符。试试下面的代码:

    public Meeting getByDay(LocalDate date) {   
        return getGuestsByDate(date).stream()
                .filter(guest -> guest.getCountry().equals("USA"))
                .reduce(new Meeting(date, new ArrayList<>()), (meeting, guest) -> {
                    meeting.guests.add(guest);
                    return meeting;
                }, (meeting1, meeting2) -> {
                    meeting1.guests.addAll(meeting2.guests);
                    return meeting1;
                });
    }
    

    您可以将这些 lambda 表达式转移到 Meeting 类或其他方法中,并使用方法引用或一个线性 lambda。

    【讨论】:

      【解决方案3】:

      我知道这不是完整的代码,但您会了解如何实现解决方案

       List<Meeting> meeting = meetings.stream()
              .filter(guest-> guest.getCountry().equals("USA"))
              .map(v->{ 
                return new Meeting(something, something);
               })
              .collect(Collectors.toList());
      

      【讨论】:

      • 此代码将返回多个会议。原始代码返回一个有多个客人的会议。
      • 好的兄弟,那样的话,你需要返回地图。要返回单个对象类型,您不能使用收集器。这适用于 Map 和 list 相关的返回类型。您现有的代码很好。
      • 收集器可以返回单个对象。
      • Collector myCollector = Collector.of( () -> new MyResult(), (a, e) -> { if (e.key.equals("2" )) { a.color = e.value; } }, (a1, a2) -> null, // 未使用,因此不工作脚手架 a -> a ); MyResult 结果 = collection.stream().collect(myCollector);
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 2011-10-19
      • 2011-10-19
      • 2018-04-14
      相关资源
      最近更新 更多