Supplier返回值能否实现递增?Java中生成递增ID实例的实现方案及场景适配问询
解决带递增ID的Person实例生成问题
嘿,这个需求挺常见的,我来一步步帮你捋清楚~
一、实现Supplier返回递增ID
你原来的Supplier<Long> ids固定返回1L,所以每次生成的Person ID都是重复的。要实现递增,核心是让Supplier持有可变状态,但Lambda表达式捕获的变量必须是final或“等效final”,所以得用能安全修改状态的容器类,这里推荐两种方案:
推荐方案(线程安全)
用AtomicLong维护计数器,它的getAndIncrement()方法会原子性地递增数值并返回之前的值,完美适配递增ID的需求:
import java.util.UUID; import java.util.function.Supplier; import java.util.concurrent.atomic.AtomicLong; class Person { long id; String name; public Person(long id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "Person{id=" + id + ", name='" + name + "'}"; } } public class Main { public static void main(String[] args) { AtomicLong idCounter = new AtomicLong(1); // 初始ID从1开始 Supplier<Long> ids = idCounter::getAndIncrement; // 方法引用简化写法 Supplier<String> names = () -> UUID.randomUUID().toString(); for (int i = 0; i < 10; i++) { Person p = new Person(ids.get(), names.get()); System.out.println(p); } } }
运行后你会得到ID从1到10连续递增的Person实例,name则是随机的UUID字符串。
单线程简化方案
如果确定不会有并发场景,也可以用final数组持有计数器(数组是引用类型,内部元素可修改):
final long[] idCounter = {1}; Supplier<Long> ids = () -> idCounter[0]++;
这种写法更简洁,但仅适用于单线程环境,多线程下会出现ID重复或丢失的问题,所以优先推荐AtomicLong。
二、Supplier是否适合这类场景?
完全适合!Supplier的核心语义就是“无参数提供一个值”,你的需求正好是每次调用获取新的递增ID/随机名称,完全贴合它的设计意图。
不过要注意两个细节:
- 有状态Supplier的复用问题:这个带计数器的Supplier是有状态的,如果在其他地方复用它,计数器会继续累加而不会重置。如果需要每次生成一批实例都从1开始,记得创建新的Supplier实例。
- 并发场景的线程安全:如果代码会在多线程环境下调用这个Supplier,一定要用
AtomicLong这类线程安全的计数器,避免线程安全问题。
如果后续需求变复杂(比如定制更多Person属性、添加生成规则),可以结合Builder模式或Factory方法,但目前的场景下,用Supplier已经足够简洁高效啦~
内容的提问来源于stack exchange,提问作者bbKing
相关产品推荐
相关产品推荐

