我的博客
  • 在Java中使用Lambda

在Java中使用Lambda

最近在工作上用Java的lambda遇到一个小问题,总结归纳一下。 假设一个字符串存着一系列商品的数据:

List<String> data = List.of("Shoes, 12.56", "HairCut, 18.55", "Pat, 129.88", "Music, 21.67");

而现在,设单价20元以上的商品是昂贵的商品,20元以下的商品是便宜的商品。我们希望有一个方法处理这个字符串,统计出来便宜的商品总价是多少,昂贵的商品总价是多少。

首先我们要有个容器来放置这个键值对,这里用一个有意义的Bean很合适

public class Item {
        private String name;
        private BigDecimal price;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public BigDecimal getPrice() {
            return price;
        }

        public void setPrice(BigDecimal price) {
            this.price = price;
        }
    }

如果我们用Java的lambda,很容易就可以写出

Map<String, BigDecimal> res = data.stream()
    .map(el -> {
            String[] namePricePair = el.split(",");
            Item item = new Item();
            item.setName(namePricePair[0].trim());
            item.setPrice(new BigDecimal(namePricePair[1].trim()));
            return item;
        }).collect(
                Collectors.groupingBy(
                        item ->
                                cheapLimit.compareTo(item.getPrice()) > 0 ? "CHEAP": "EXPENSIVE",
                        Collectors.reducing(BigDecimal.ZERO, item-> item.getPrice(), (init, acc)->init.add(acc))
                )
        );

Java的ThreadLocal遇到的坑

还是刚刚被分配到项目组的时候,那个时候碰到一个很奇怪的问题,用户A的数据经常和用户B的数据发生混淆,最后在排查代码的时候发现用户相关的数据是从ThreadLocal中取的,而请求的线程池没有将已经过期的用户数据清理掉,才导致了这个现象。

public class Main {
    public static void main(String[] args) {
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        // use thread pool to demo something
        ExecutorService service = Executors.newFixedThreadPool(2);
        CompletableFuture[] futures = new CompletableFuture[10];
        for(int i = 0; i < 10; i++) {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                String threadLocalStr = Thread.currentThread().getName();
                if (threadLocal.get() != null) {
                    System.out.println(threadLocal.get());
                } else {
                    System.out.println("not find in thread local");
                    threadLocal.set(threadLocalStr);
                }
                return threadLocalStr;
            }, service);
            futures[i] = future;
        }
        CompletableFuture.allOf(futures);
        service.shutdown();
    }
}

上边这个代码中,ThreadLocal只有两个值,因为只有两个线程。 所以当使用和线程池时,复用这个线程要清空ThreadLocal

最近更新: 2026/3/15 14:17
Contributors: Keyang Li