【问题标题】:Java Stream API: Change values by criteriaJava Stream API:按条件更改值
【发布时间】:2020-04-03 13:43:27
【问题描述】:

有Java类:

public class Item {
  private String dateModified;
  private Integer color;
}

在哪里dateModified in format "hh:mm:ss",

ArrayList<Item> 列表,其中包含 10 个元素。

所以我想检查我的清单并:

if now() - dateModified > 1 min , then change color to 1
if now() - dateModified > 5 min , then change color to 2
if now() - dateModified > 10 min, then change color to 3

如何用 Java Stream API 实现?

更新: 我在下面的代码中实现了我的任务。它按预期工作,但看起来很大且不优雅。 我忘了说这个列表应该是可变的。

 list.stream()
 .map(c -> {
  if (compareTime(c.getDateModified(), 600)) {
     c.setColor(3);                       
  } else if (compareTime(c.getDateModified(), 300)) {
     c.setColor(2);
  } else if (compareTime(c.getDateModified(), 60)) {
     c.setColor(1);
  }
     return c;
  }).collect(Collectors.toList());


private boolean compareTime(String dateModified, Integer delta) {
        boolean result = false;
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        Integer secondsDateModified = Integer.parseInt(dateModified.substring(0, 2)) * 3600 +
        Integer.parseInt(dateModified.substring(3, 5)) * 60 +
        Integer.parseInt(dateModified.substring(6, 8)) ;
        Integer secondsNow = hour * 3600 + minute * 60 + second ;
        Integer delta1 = secondsNow - secondsDateModified;
        if ((delta1) > delta) {
            result = true;
        }
        return result;
    }

感谢任何改进代码的建议。

【问题讨论】:

  • 首先你需要写一些代码
  • 为什么你认为 Java Stream API 很适合这里?

标签: java java-stream


【解决方案1】:

存储一个 LocalTime 对象,而不是存储一个字符串作为时间。此外,不要改变原始项目,而是返回项目或具有新颜色的新项目。

  public static class Item {

        private final LocalTime dateModified;

        private final Integer color;

        public Item(LocalTime dateModified, Integer color) {
            this.dateModified = dateModified;
            this.color = color;
        }

        public Item withColor(int color) {
            return new Item(dateModified, color);
        }

        public LocalTime getDateModified() {
            return dateModified;
        }

        public Integer getColor() {
            return color;
        }
    }

例子

    public static void main(String[] args) {
        List<Item> items = new ArrayList<>(Arrays.asList(
                new Item(LocalTime.parse("10:30:00"), 0),
                new Item(LocalTime.parse("10:30:01"), 255)));

        LocalTime now = LocalTime.now();

        List<Item> modified = items.stream().map(item -> {
            long minutes = Duration.between(item.dateModified, LocalTime.now())
                    .toMinutes();

            return minutes >= 1 ? 
                    item.withColor(minutes >= 10 ? 3 : minutes >= 5 ? 2 : 1) : item;
        }).collect(Collectors.toList());
    }

【讨论】:

    【解决方案2】:

    如何使用单独的流来更新每个所需的项目范围:

    public static void updateColor(List<Item> items) {
        final LocalTime now = LocalTime.now();
        final Function<Item, Long> getDurationInMinutes = item -> Duration.between(LocalTime.parse(item.dateModified), now).toMinutes()
    
        final Predicate<Item> betweenOneAndFive = item -> {
            long duration = getDurationInMinutes.apply(item);
            return duration > ONE && duration <= FIVE;
        };
    
        final Predicate<Item> betweenFiveAndTen = item -> {
            long duration = getDurationInMinutes.apply(item);
            return duration > FIVE && duration <= TEN;
        };
    
        final Predicate<Item> greaterThanTen = item -> getDurationInMinutes.apply(item) > TEN;
    
    
        items.stream().filter(betweenOneAndFive).forEach(item -> item.color = 1);
        items.stream().filter(betweenFiveAndTen).forEach(item -> item.color = 2);
        items.stream().filter(greaterThanTen).forEach(item -> item.color = 3);
    }
    

    【讨论】:

      【解决方案3】:

      这是从分钟差到数字的适当映射函数的问题。

      items.forEach(item -> item.setColor(((int) Math.floor(differenceInMinutes(item.getDateModified(), now) + 5)) / 5));
      

      注意,differenceInMinutes 方法将返回浮点运算的差异。

      采取的步骤是:

      1. 找出与now 的项目日期的分钟差。
      2. 将结果转换为int,其工作方式类似于Math.floor
      3. 结果加 5。
      4. 除以 5。

      因此,例如 1.3 分钟将导致 (1+5)/5,即 1。

      9.8 分钟将导致 (9+5)/5,即 2。

      等等。

      【讨论】:

        【解决方案4】:

        首先,正如 Jason 所说,不要在流中改变你的项目,制作副本。 (What is the danger of side effects in Java 8 Streams?)。

        您将需要中间操作:

        long getElapseTimeSinceModification(Item item) {
            return ChronoUnit.MINUTES.between(LocalTime.parse(item.dateModified), LocalDate.now());
        }
        
        Optional<Integer> getNewColor(long elapseTimeSinceModification) {
            if (elapseTimeSinceModification > 10) {
                return Optional.of(3);
            } else if (elapseTimeSinceModification > 5) {
                return Optional.of(2);
            } else if (elapseTimeSinceModification > 1) {
                return Optional.of(1);
            }
        
            return Optional.empty();
        }
        
        Item withNewColor(int newColor, Item item) {
            Item newTtem = new Item();
            newTtem.color = newColor;
            newTtem.dateModified = item.dateModified;
            return newTtem;
        }
        

        然后您可以将它们应用到您的流中:

        List<Item> itemsWithNewColor = items.stream()
                .map(item -> getNewColor(getElapseTimeSinceModification(item))
                        .map(newColor -> withNewColor(newColor , item))
                        .orElse(i))
                .collect(Collectors.toList());
        

        【讨论】:

          猜你喜欢
          • 2020-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-04
          相关资源
          最近更新 更多