How to reference the result of reduce() operation in Java 8?












9















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:




  1. I am unable to make the first argument of mkString a generic Collection reference like Collection<Object> c and have invokers call with ANY type of collection.


  2. 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);
}









share|improve this question




















  • 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
















9















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:




  1. I am unable to make the first argument of mkString a generic Collection reference like Collection<Object> c and have invokers call with ANY type of collection.


  2. 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);
}









share|improve this question




















  • 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














9












9








9


1






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:




  1. I am unable to make the first argument of mkString a generic Collection reference like Collection<Object> c and have invokers call with ANY type of collection.


  2. 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);
}









share|improve this question
















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:




  1. I am unable to make the first argument of mkString a generic Collection reference like Collection<Object> c and have invokers call with ANY type of collection.


  2. 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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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














  • 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












5 Answers
5






active

oldest

votes


















9














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.






share|improve this answer
























  • 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











  • 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



















7














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
}





share|improve this answer
























  • 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 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











  • @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



















5














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.






share|improve this answer
























  • 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



















1














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));

}





share|improve this answer































    0














    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.






    share|improve this answer
























    • 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











    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    9














    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.






    share|improve this answer
























    • 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











    • 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
















    9














    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.






    share|improve this answer
























    • 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











    • 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














    9












    9








    9







    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.






    share|improve this answer













    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Vladimir MatveevVladimir Matveev

    69.8k15169213




    69.8k15169213













    • 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











    • 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











    • 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













    7














    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
    }





    share|improve this answer
























    • 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 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











    • @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
















    7














    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
    }





    share|improve this answer
























    • 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 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











    • @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














    7












    7








    7







    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
    }





    share|improve this answer













    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
    }






    share|improve this answer












    share|improve this answer



    share|improve this answer










    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 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











    • @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











    • 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











    • @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











    5














    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.






    share|improve this answer
























    • 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
















    5














    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.






    share|improve this answer
























    • 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














    5












    5








    5







    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.






    share|improve this answer













    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    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



















    • 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











    1














    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));

    }





    share|improve this answer




























      1














      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));

      }





      share|improve this answer


























        1












        1








        1







        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));

        }





        share|improve this answer













        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));

        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 22 hours ago









        EugeneEugene

        70.1k999165




        70.1k999165























            0














            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.






            share|improve this answer
























            • 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
















            0














            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.






            share|improve this answer
























            • 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














            0












            0








            0







            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.






            share|improve this answer













            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered yesterday









            QuintecQuintec

            587518




            587518













            • 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



















            • 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

















            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


















            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            RAC Tourist Trophy