How to reference the result of reduce() operation in Java 8?
I was trying to write a mkString
function in Java8, a la Scala's useful mkString
and ran into 2 issues that I could use some help on:
I am unable to make the first argument of
mkString
a generic Collection reference likeCollection<Object> c
and have invokers call with ANY type of collection.Unable to reference the returned result of
reduce()
in-line to access the result's length to remove the extra leading separator.
Here's the code :
public static void main(String args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(mkString(numbers, ","));
}
public static String mkString(Collection<Integer> c, String sep) {
return c.stream()
.map(e -> String.valueOf(e))
.reduce("", (a, b) -> a + sep + b)
.substring(1, <<>>.length);
}
java scala lambda java-stream reduce
add a comment |
I was trying to write a mkString
function in Java8, a la Scala's useful mkString
and ran into 2 issues that I could use some help on:
I am unable to make the first argument of
mkString
a generic Collection reference likeCollection<Object> c
and have invokers call with ANY type of collection.Unable to reference the returned result of
reduce()
in-line to access the result's length to remove the extra leading separator.
Here's the code :
public static void main(String args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(mkString(numbers, ","));
}
public static String mkString(Collection<Integer> c, String sep) {
return c.stream()
.map(e -> String.valueOf(e))
.reduce("", (a, b) -> a + sep + b)
.substring(1, <<>>.length);
}
java scala lambda java-stream reduce
2
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago
add a comment |
I was trying to write a mkString
function in Java8, a la Scala's useful mkString
and ran into 2 issues that I could use some help on:
I am unable to make the first argument of
mkString
a generic Collection reference likeCollection<Object> c
and have invokers call with ANY type of collection.Unable to reference the returned result of
reduce()
in-line to access the result's length to remove the extra leading separator.
Here's the code :
public static void main(String args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(mkString(numbers, ","));
}
public static String mkString(Collection<Integer> c, String sep) {
return c.stream()
.map(e -> String.valueOf(e))
.reduce("", (a, b) -> a + sep + b)
.substring(1, <<>>.length);
}
java scala lambda java-stream reduce
I was trying to write a mkString
function in Java8, a la Scala's useful mkString
and ran into 2 issues that I could use some help on:
I am unable to make the first argument of
mkString
a generic Collection reference likeCollection<Object> c
and have invokers call with ANY type of collection.Unable to reference the returned result of
reduce()
in-line to access the result's length to remove the extra leading separator.
Here's the code :
public static void main(String args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(mkString(numbers, ","));
}
public static String mkString(Collection<Integer> c, String sep) {
return c.stream()
.map(e -> String.valueOf(e))
.reduce("", (a, b) -> a + sep + b)
.substring(1, <<>>.length);
}
java scala lambda java-stream reduce
java scala lambda java-stream reduce
edited yesterday
GBlodgett
9,85841733
9,85841733
asked yesterday
212212
3182416
3182416
2
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago
add a comment |
2
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago
2
2
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago
add a comment |
5 Answers
5
active
oldest
votes
Note that if you're doing this not for self-education but to actually use it in some production code, you might want to consider the built-in Collectors.joining
collector:
String result = numbers.stream().collect(Collectors.joining(","));
It has several overloads, similar to Scala's mkString
.
Additionally, there is the String.join
method, but it works only for collections of strings.
this would not compile though.Collectors::joining
is expecting aCharSequence
, you would also need to provide a mapper
– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings
– Ferrybig
17 hours ago
add a comment |
You can do it like :
public static <T> String mkString(Collection<T> c, String sep) { // generic impl
return c.stream()
.map(String::valueOf)
.reduce("", (a, b) -> a + sep + b)
.substring(1); // substring implementation to strip leading character
}
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed.Collection<?>
would work just as well.
– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed fromString s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?
– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
|
show 3 more comments
If I remember my java correctly, you can declare the argument type as Collection<?>
to be able to pass a collection of any objects.
As to biting the separator off, I think, just .substring(1)
will do what you want.
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
T
and?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.
– Dima
yesterday
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters
– Bergi
18 hours ago
|
show 3 more comments
Any type of collection in java means Collection<?>
, which semantically is the same as Collection<T>
(in your case), it is said that if the type parameter is used only once) it can safely be replaced with a wildcard. But, since you want to be able to concat any collection, you should also ask for the callers to supply a Function
that would transform from that type to a String representation, thus your method would become:
public static <T> String mkString(Collection<T> c,
Function<T, ? extends CharSequence> mapper,
String sep) {
return c.stream()
.map(mapper)
.collect(Collectors.joining(sep));
}
add a comment |
You can utilize String.join
with a generic type:
public static <T> String mkString(Collection<T> c, String sep) {
return String.join(sep, c.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.toList()));
}
Here it is in action with both Strings and other objects.
you are collecting to aList
, only to be able to callString::join
? there isCollectors.joining
for that purpose. And you assume thatString::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.
– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
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%2f54496864%2fhow-to-reference-the-result-of-reduce-operation-in-java-8%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
Note that if you're doing this not for self-education but to actually use it in some production code, you might want to consider the built-in Collectors.joining
collector:
String result = numbers.stream().collect(Collectors.joining(","));
It has several overloads, similar to Scala's mkString
.
Additionally, there is the String.join
method, but it works only for collections of strings.
this would not compile though.Collectors::joining
is expecting aCharSequence
, you would also need to provide a mapper
– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings
– Ferrybig
17 hours ago
add a comment |
Note that if you're doing this not for self-education but to actually use it in some production code, you might want to consider the built-in Collectors.joining
collector:
String result = numbers.stream().collect(Collectors.joining(","));
It has several overloads, similar to Scala's mkString
.
Additionally, there is the String.join
method, but it works only for collections of strings.
this would not compile though.Collectors::joining
is expecting aCharSequence
, you would also need to provide a mapper
– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings
– Ferrybig
17 hours ago
add a comment |
Note that if you're doing this not for self-education but to actually use it in some production code, you might want to consider the built-in Collectors.joining
collector:
String result = numbers.stream().collect(Collectors.joining(","));
It has several overloads, similar to Scala's mkString
.
Additionally, there is the String.join
method, but it works only for collections of strings.
Note that if you're doing this not for self-education but to actually use it in some production code, you might want to consider the built-in Collectors.joining
collector:
String result = numbers.stream().collect(Collectors.joining(","));
It has several overloads, similar to Scala's mkString
.
Additionally, there is the String.join
method, but it works only for collections of strings.
answered yesterday
Vladimir MatveevVladimir Matveev
69.8k15169213
69.8k15169213
this would not compile though.Collectors::joining
is expecting aCharSequence
, you would also need to provide a mapper
– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings
– Ferrybig
17 hours ago
add a comment |
this would not compile though.Collectors::joining
is expecting aCharSequence
, you would also need to provide a mapper
– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings
– Ferrybig
17 hours ago
this would not compile though.
Collectors::joining
is expecting a CharSequence
, you would also need to provide a mapper– Eugene
22 hours ago
this would not compile though.
Collectors::joining
is expecting a CharSequence
, you would also need to provide a mapper– Eugene
22 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
If you are doing this for self-education, consider writing the equivalent collector yourself (or not quite the same to fix the problem Eugene mentions).
– Alexey Romanov
20 hours ago
Even though this solution needs the
.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings– Ferrybig
17 hours ago
Even though this solution needs the
.map
, I still think this is the best solution as it is the most performant, since its uses a string builder internally, as opposed to concatenating strings– Ferrybig
17 hours ago
add a comment |
You can do it like :
public static <T> String mkString(Collection<T> c, String sep) { // generic impl
return c.stream()
.map(String::valueOf)
.reduce("", (a, b) -> a + sep + b)
.substring(1); // substring implementation to strip leading character
}
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed.Collection<?>
would work just as well.
– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed fromString s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?
– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
|
show 3 more comments
You can do it like :
public static <T> String mkString(Collection<T> c, String sep) { // generic impl
return c.stream()
.map(String::valueOf)
.reduce("", (a, b) -> a + sep + b)
.substring(1); // substring implementation to strip leading character
}
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed.Collection<?>
would work just as well.
– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed fromString s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?
– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
|
show 3 more comments
You can do it like :
public static <T> String mkString(Collection<T> c, String sep) { // generic impl
return c.stream()
.map(String::valueOf)
.reduce("", (a, b) -> a + sep + b)
.substring(1); // substring implementation to strip leading character
}
You can do it like :
public static <T> String mkString(Collection<T> c, String sep) { // generic impl
return c.stream()
.map(String::valueOf)
.reduce("", (a, b) -> a + sep + b)
.substring(1); // substring implementation to strip leading character
}
answered yesterday
nullpointernullpointer
47.2k11100191
47.2k11100191
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed.Collection<?>
would work just as well.
– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed fromString s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?
– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
|
show 3 more comments
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed.Collection<?>
would work just as well.
– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed fromString s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?
– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
Thanks for addressing both issues. However, does this mean that there is no syntax to access the result of reduce() without assignment?
– 212
yesterday
T
isn't needed. Collection<?>
would work just as well.– John Kugelman
yesterday
T
isn't needed. Collection<?>
would work just as well.– John Kugelman
yesterday
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed from
String s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?– Eugene
22 hours ago
@nullpointer this is not associative, and thus breaks the specification... what would you expect to be printed from
String s = Stream.of("a", "b", "c", "d") .parallel() .reduce("", (a, b) -> a + "-" + b); System.out.println(s);
for example?– Eugene
22 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@212 well that depends on the operation you want to perform primarily I would say.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
@Eugene not sure about the associativity here(required or not), I just proposed the to commented out line of codes mainly to focus on the question form OP.
– nullpointer
21 hours ago
|
show 3 more comments
If I remember my java correctly, you can declare the argument type as Collection<?>
to be able to pass a collection of any objects.
As to biting the separator off, I think, just .substring(1)
will do what you want.
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
T
and?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.
– Dima
yesterday
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters
– Bergi
18 hours ago
|
show 3 more comments
If I remember my java correctly, you can declare the argument type as Collection<?>
to be able to pass a collection of any objects.
As to biting the separator off, I think, just .substring(1)
will do what you want.
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
T
and?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.
– Dima
yesterday
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters
– Bergi
18 hours ago
|
show 3 more comments
If I remember my java correctly, you can declare the argument type as Collection<?>
to be able to pass a collection of any objects.
As to biting the separator off, I think, just .substring(1)
will do what you want.
If I remember my java correctly, you can declare the argument type as Collection<?>
to be able to pass a collection of any objects.
As to biting the separator off, I think, just .substring(1)
will do what you want.
answered yesterday
DimaDima
24.9k32235
24.9k32235
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
T
and?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.
– Dima
yesterday
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters
– Bergi
18 hours ago
|
show 3 more comments
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
T
and?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.
– Dima
yesterday
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters
– Bergi
18 hours ago
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
docs.oracle.com/javase/tutorial/extra/generics/methods.html seems to favor generic methods compared to Collection<?> approach.
– 212
yesterday
3
3
T
and ?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer ?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.– Dima
yesterday
T
and ?
is absolutely the same thing in this context. So, it's a matter of taste. I personally prefer ?
because it makes it clear that the implementation does not use or need the type information, and that the collection is intended to be mutated. It is also a common indicator of the call-site variance.– Dima
yesterday
1
1
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@212: I think you must have misread the page that you link to. It's very explicit that "one should use wildcards" in cases where "[t]he return type doesn't depend on the type parameter, nor does any other argument to the method", and dedicates multiple paragraphs to that guidance. So Dima is quite right.
– ruakh
yesterday
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
@Dima in simpler words (IIRC that is also present in effective java): if a type parameter is used only once, it can be replaced by a wildcard.
– Eugene
22 hours ago
.substring(1)
won't work if the separator consists of multiple characters– Bergi
18 hours ago
.substring(1)
won't work if the separator consists of multiple characters– Bergi
18 hours ago
|
show 3 more comments
Any type of collection in java means Collection<?>
, which semantically is the same as Collection<T>
(in your case), it is said that if the type parameter is used only once) it can safely be replaced with a wildcard. But, since you want to be able to concat any collection, you should also ask for the callers to supply a Function
that would transform from that type to a String representation, thus your method would become:
public static <T> String mkString(Collection<T> c,
Function<T, ? extends CharSequence> mapper,
String sep) {
return c.stream()
.map(mapper)
.collect(Collectors.joining(sep));
}
add a comment |
Any type of collection in java means Collection<?>
, which semantically is the same as Collection<T>
(in your case), it is said that if the type parameter is used only once) it can safely be replaced with a wildcard. But, since you want to be able to concat any collection, you should also ask for the callers to supply a Function
that would transform from that type to a String representation, thus your method would become:
public static <T> String mkString(Collection<T> c,
Function<T, ? extends CharSequence> mapper,
String sep) {
return c.stream()
.map(mapper)
.collect(Collectors.joining(sep));
}
add a comment |
Any type of collection in java means Collection<?>
, which semantically is the same as Collection<T>
(in your case), it is said that if the type parameter is used only once) it can safely be replaced with a wildcard. But, since you want to be able to concat any collection, you should also ask for the callers to supply a Function
that would transform from that type to a String representation, thus your method would become:
public static <T> String mkString(Collection<T> c,
Function<T, ? extends CharSequence> mapper,
String sep) {
return c.stream()
.map(mapper)
.collect(Collectors.joining(sep));
}
Any type of collection in java means Collection<?>
, which semantically is the same as Collection<T>
(in your case), it is said that if the type parameter is used only once) it can safely be replaced with a wildcard. But, since you want to be able to concat any collection, you should also ask for the callers to supply a Function
that would transform from that type to a String representation, thus your method would become:
public static <T> String mkString(Collection<T> c,
Function<T, ? extends CharSequence> mapper,
String sep) {
return c.stream()
.map(mapper)
.collect(Collectors.joining(sep));
}
answered 22 hours ago
EugeneEugene
70.1k999165
70.1k999165
add a comment |
add a comment |
You can utilize String.join
with a generic type:
public static <T> String mkString(Collection<T> c, String sep) {
return String.join(sep, c.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.toList()));
}
Here it is in action with both Strings and other objects.
you are collecting to aList
, only to be able to callString::join
? there isCollectors.joining
for that purpose. And you assume thatString::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.
– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
add a comment |
You can utilize String.join
with a generic type:
public static <T> String mkString(Collection<T> c, String sep) {
return String.join(sep, c.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.toList()));
}
Here it is in action with both Strings and other objects.
you are collecting to aList
, only to be able to callString::join
? there isCollectors.joining
for that purpose. And you assume thatString::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.
– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
add a comment |
You can utilize String.join
with a generic type:
public static <T> String mkString(Collection<T> c, String sep) {
return String.join(sep, c.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.toList()));
}
Here it is in action with both Strings and other objects.
You can utilize String.join
with a generic type:
public static <T> String mkString(Collection<T> c, String sep) {
return String.join(sep, c.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.toList()));
}
Here it is in action with both Strings and other objects.
answered yesterday
QuintecQuintec
587518
587518
you are collecting to aList
, only to be able to callString::join
? there isCollectors.joining
for that purpose. And you assume thatString::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.
– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
add a comment |
you are collecting to aList
, only to be able to callString::join
? there isCollectors.joining
for that purpose. And you assume thatString::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.
– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
you are collecting to a
List
, only to be able to call String::join
? there is Collectors.joining
for that purpose. And you assume that String::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.– Eugene
22 hours ago
you are collecting to a
List
, only to be able to call String::join
? there is Collectors.joining
for that purpose. And you assume that String::valueOf
will provide any meaningful String representation of the object, which might not hold true. A better way would be to pass a mapper also.– Eugene
22 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
@Eugene Forgot about collectors.joining, but now it's already an answer, so I'll keep it the way it is. Passing a mapper, while useful, is out of the scope of the question imo. Thanks for the feedback.
– Quintec
12 hours ago
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.
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%2f54496864%2fhow-to-reference-the-result-of-reduce-operation-in-java-8%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
2
Using reduce to build strings is remarkably inefficient. Every element requires a full copy of the accumulator string. It's much better to use a dedicated joining function instead, which can use something like a string builder.
– Alexander
22 hours ago