0

I feel I have some wrong interpretation of Supplier use-case. Here is an example where I want to add value to a List. But when I try to fetch the list from supplier, it shows as empty.

Supplier<List<String>> str = ArrayList::new;
        
str.get().add("Hi");
System.out.println(str.get().size());

Returns: 0

mitali
  • 87
  • 8
  • You are missing the big picture. This is not what `Supplier` is used for. Check [When we should use Supplier in Java 8?](https://stackoverflow.com/q/40244571/10819573) – Arvind Kumar Avinash Jul 05 '21 at 09:56

2 Answers2

4

Supplier<List<String>> is a function that gets invoked whenever the get method is run.

In your case, str is similar to the following lambda expression:

Supplier<List<String>> str = () -> new ArrayList<>();

Which means that every time str.get() is called, the function gets called, and the body new ArrayList<>() is executed, thus resulting in a new list every time.

If you want the Supplier to always return the same list, then you need to capture it:

List<String> list = new ArrayList<>();
Supplier<List<String>> str = () -> list;

This way, every time str.get() runs, it will just return the same list it captured. But, IMO, this doesn't seem like good practice, it would seem rather correct to just keep a reference to the variable instead of keeping it behind a Supplier (which implies a function producing a value).

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • 1
    There’s also the option to create a new, decorating supplier that will always perform the add operation on the created list `{ Supplier> tmp = str; str = () -> { List list = tmp.get(); list.add("Hi"); return list; }; }` – Holger Jul 06 '21 at 10:21
2

Each call to str.get() will instantiate a new List, which will be empty.

Your two calls to str.get() return two different instances. You added an element to the first List, but the second List is empty.

You have to store a reference to the created List if you want to have access to it:

List<String> list = str.get();
list.add("Hi");
System.out.println(list.size());
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Eran, thank you for the explanation. My use case is this. I have to declare several type of Lists in a method. Now I want to make them lazy so have wrapped them with Supplier. How can I reference the list inside the Supplier get() call. – mitali Jul 05 '21 at 07:22
  • @mitali It's hard to understand what exactly you need without seeing your actual code. In general, each time you call the `Supplier`'s `get()`, you have to store a reference to the created `List` somewhere. Otherwise it's useless. – Eran Jul 05 '21 at 07:27