Java Map computeIfAbsent issue
So I found a curiosity with Java's Map computeIfAbsent (using java8) method and I hope someone can tell me why this is happening as I can not really follow the logic behind that issue.
So, I have a Map with a key (obviously) and the value is a list and I use the computeIfAbsent to create a new list when a key is not set yet. Now when I use an Integer as key I can use the following:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
But when I use a String as key trying to use
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
I get the error that The method computeIfAbsent(String, Function<? super String,? extends List<Object>>) in the type Map<String,List<Object>> is not applicable for the arguments (String, ArrayList::new). Is there just the implementation missing? Using a String key I have to use the method like that, which is then working again.
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());
Maybe someone can enlighten me about that. Thanks :)
java java-8 functional-programming
add a comment |
So I found a curiosity with Java's Map computeIfAbsent (using java8) method and I hope someone can tell me why this is happening as I can not really follow the logic behind that issue.
So, I have a Map with a key (obviously) and the value is a list and I use the computeIfAbsent to create a new list when a key is not set yet. Now when I use an Integer as key I can use the following:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
But when I use a String as key trying to use
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
I get the error that The method computeIfAbsent(String, Function<? super String,? extends List<Object>>) in the type Map<String,List<Object>> is not applicable for the arguments (String, ArrayList::new). Is there just the implementation missing? Using a String key I have to use the method like that, which is then working again.
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());
Maybe someone can enlighten me about that. Thanks :)
java java-8 functional-programming
As a side note, Guava'sMultiMapalready implements what you're looking for.
– chrylis
Dec 19 '18 at 7:28
and its worth mentioning the type ofmapused in the code for clarity of the question
– nullpointer
Dec 19 '18 at 7:46
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16
add a comment |
So I found a curiosity with Java's Map computeIfAbsent (using java8) method and I hope someone can tell me why this is happening as I can not really follow the logic behind that issue.
So, I have a Map with a key (obviously) and the value is a list and I use the computeIfAbsent to create a new list when a key is not set yet. Now when I use an Integer as key I can use the following:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
But when I use a String as key trying to use
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
I get the error that The method computeIfAbsent(String, Function<? super String,? extends List<Object>>) in the type Map<String,List<Object>> is not applicable for the arguments (String, ArrayList::new). Is there just the implementation missing? Using a String key I have to use the method like that, which is then working again.
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());
Maybe someone can enlighten me about that. Thanks :)
java java-8 functional-programming
So I found a curiosity with Java's Map computeIfAbsent (using java8) method and I hope someone can tell me why this is happening as I can not really follow the logic behind that issue.
So, I have a Map with a key (obviously) and the value is a list and I use the computeIfAbsent to create a new list when a key is not set yet. Now when I use an Integer as key I can use the following:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
But when I use a String as key trying to use
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
I get the error that The method computeIfAbsent(String, Function<? super String,? extends List<Object>>) in the type Map<String,List<Object>> is not applicable for the arguments (String, ArrayList::new). Is there just the implementation missing? Using a String key I have to use the method like that, which is then working again.
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());
Maybe someone can enlighten me about that. Thanks :)
java java-8 functional-programming
java java-8 functional-programming
edited Dec 19 '18 at 7:29
asked Dec 19 '18 at 7:27
Fussel
64313
64313
As a side note, Guava'sMultiMapalready implements what you're looking for.
– chrylis
Dec 19 '18 at 7:28
and its worth mentioning the type ofmapused in the code for clarity of the question
– nullpointer
Dec 19 '18 at 7:46
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16
add a comment |
As a side note, Guava'sMultiMapalready implements what you're looking for.
– chrylis
Dec 19 '18 at 7:28
and its worth mentioning the type ofmapused in the code for clarity of the question
– nullpointer
Dec 19 '18 at 7:46
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16
As a side note, Guava's
MultiMap already implements what you're looking for.– chrylis
Dec 19 '18 at 7:28
As a side note, Guava's
MultiMap already implements what you're looking for.– chrylis
Dec 19 '18 at 7:28
and its worth mentioning the type of
map used in the code for clarity of the question– nullpointer
Dec 19 '18 at 7:46
and its worth mentioning the type of
map used in the code for clarity of the question– nullpointer
Dec 19 '18 at 7:46
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16
add a comment |
2 Answers
2
active
oldest
votes
The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.
Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.
To make it clearer:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));
so it will create an ArrayList with initial capacity of 1.
On the other hand:
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
where k is a String, so it doesn't pass compilation.
And more specifically,1 -> ArrayList::newdoes not in fact produce a list with the value1inserted.
– chrylis
Dec 19 '18 at 7:30
So when usingArrayList::newthe given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?
– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, theListbeingList<String>makes no difference, since the key is not added to the List, it is passed to theArrayListconstructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).
– Eran
Dec 19 '18 at 7:45
2
@Fussel If you replace1with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An emptyArrayListcan consume an arbitrary amount of memory depending on the capacity.
– Giacomo Alzetta
Dec 19 '18 at 15:08
|
show 2 more comments
Your second attempt
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
would actually be equal to
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
and since ArrayList has no constructor taking a String as a parameter, it doesn't work. The first example works as it creates a list with one element.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53846428%2fjava-map-computeifabsent-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.
Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.
To make it clearer:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));
so it will create an ArrayList with initial capacity of 1.
On the other hand:
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
where k is a String, so it doesn't pass compilation.
And more specifically,1 -> ArrayList::newdoes not in fact produce a list with the value1inserted.
– chrylis
Dec 19 '18 at 7:30
So when usingArrayList::newthe given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?
– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, theListbeingList<String>makes no difference, since the key is not added to the List, it is passed to theArrayListconstructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).
– Eran
Dec 19 '18 at 7:45
2
@Fussel If you replace1with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An emptyArrayListcan consume an arbitrary amount of memory depending on the capacity.
– Giacomo Alzetta
Dec 19 '18 at 15:08
|
show 2 more comments
The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.
Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.
To make it clearer:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));
so it will create an ArrayList with initial capacity of 1.
On the other hand:
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
where k is a String, so it doesn't pass compilation.
And more specifically,1 -> ArrayList::newdoes not in fact produce a list with the value1inserted.
– chrylis
Dec 19 '18 at 7:30
So when usingArrayList::newthe given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?
– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, theListbeingList<String>makes no difference, since the key is not added to the List, it is passed to theArrayListconstructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).
– Eran
Dec 19 '18 at 7:45
2
@Fussel If you replace1with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An emptyArrayListcan consume an arbitrary amount of memory depending on the capacity.
– Giacomo Alzetta
Dec 19 '18 at 15:08
|
show 2 more comments
The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.
Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.
To make it clearer:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));
so it will create an ArrayList with initial capacity of 1.
On the other hand:
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
where k is a String, so it doesn't pass compilation.
The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.
Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.
To make it clearer:
List<Object> list = map.computeIfAbsent(1, ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));
so it will create an ArrayList with initial capacity of 1.
On the other hand:
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
behaves similar to:
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
where k is a String, so it doesn't pass compilation.
edited Dec 19 '18 at 7:36
answered Dec 19 '18 at 7:29
Eran
279k37452537
279k37452537
And more specifically,1 -> ArrayList::newdoes not in fact produce a list with the value1inserted.
– chrylis
Dec 19 '18 at 7:30
So when usingArrayList::newthe given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?
– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, theListbeingList<String>makes no difference, since the key is not added to the List, it is passed to theArrayListconstructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).
– Eran
Dec 19 '18 at 7:45
2
@Fussel If you replace1with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An emptyArrayListcan consume an arbitrary amount of memory depending on the capacity.
– Giacomo Alzetta
Dec 19 '18 at 15:08
|
show 2 more comments
And more specifically,1 -> ArrayList::newdoes not in fact produce a list with the value1inserted.
– chrylis
Dec 19 '18 at 7:30
So when usingArrayList::newthe given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?
– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, theListbeingList<String>makes no difference, since the key is not added to the List, it is passed to theArrayListconstructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).
– Eran
Dec 19 '18 at 7:45
2
@Fussel If you replace1with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An emptyArrayListcan consume an arbitrary amount of memory depending on the capacity.
– Giacomo Alzetta
Dec 19 '18 at 15:08
And more specifically,
1 -> ArrayList::new does not in fact produce a list with the value 1 inserted.– chrylis
Dec 19 '18 at 7:30
And more specifically,
1 -> ArrayList::new does not in fact produce a list with the value 1 inserted.– chrylis
Dec 19 '18 at 7:30
So when using
ArrayList::new the given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?– Fussel
Dec 19 '18 at 7:33
So when using
ArrayList::new the given key is inserted into the list? That in my example I'd have a List with the value 1 already in it?– Fussel
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
@chrylis did the OP expect such behavior (1 being inserted into the List)? I didn't see that mentioned in the question.
– Eran
Dec 19 '18 at 7:33
1
1
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, the
List being List<String> makes no difference, since the key is not added to the List, it is passed to the ArrayList constructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).– Eran
Dec 19 '18 at 7:45
@Fussel the key will not be part of the list either way, but you are correct to use lambda expressions in both cases (Integer and String key). No, the
List being List<String> makes no difference, since the key is not added to the List, it is passed to the ArrayList constructor (which doesn't work for Strings, since ArrayList has no constructor that accepts a String).– Eran
Dec 19 '18 at 7:45
2
2
@Fussel If you replace
1 with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An empty ArrayList can consume an arbitrary amount of memory depending on the capacity.– Giacomo Alzetta
Dec 19 '18 at 15:08
@Fussel If you replace
1 with 1 billion you might get a memory error since Java will try to allocate an array that has the capacity of storing 1 billion elements. Note that capacity != actual elements. An empty ArrayList can consume an arbitrary amount of memory depending on the capacity.– Giacomo Alzetta
Dec 19 '18 at 15:08
|
show 2 more comments
Your second attempt
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
would actually be equal to
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
and since ArrayList has no constructor taking a String as a parameter, it doesn't work. The first example works as it creates a list with one element.
add a comment |
Your second attempt
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
would actually be equal to
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
and since ArrayList has no constructor taking a String as a parameter, it doesn't work. The first example works as it creates a list with one element.
add a comment |
Your second attempt
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
would actually be equal to
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
and since ArrayList has no constructor taking a String as a parameter, it doesn't work. The first example works as it creates a list with one element.
Your second attempt
List<Object> list = map.computeIfAbsent("key", ArrayList::new);
would actually be equal to
List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));
and since ArrayList has no constructor taking a String as a parameter, it doesn't work. The first example works as it creates a list with one element.
answered Dec 19 '18 at 7:30
Jan Gassen
1,69011531
1,69011531
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53846428%2fjava-map-computeifabsent-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
As a side note, Guava's
MultiMapalready implements what you're looking for.– chrylis
Dec 19 '18 at 7:28
and its worth mentioning the type of
mapused in the code for clarity of the question– nullpointer
Dec 19 '18 at 7:46
I'm pretty sure this is a duplicate, but it's hard to find :-/
– Marco13
Dec 19 '18 at 22:14
Ah, there it is: stackoverflow.com/q/35296734/3182664 - any objections to close this one as a duplicate of the other?
– Marco13
Dec 19 '18 at 22:16