Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  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);
}
like image 730
212 Avatar asked Feb 02 '19 19:02

212


People also ask

What is reduce () in java8?

In Java, reducing is a terminal operation that aggregates a stream into a type or a primitive type. Java 8 provides Stream API contains set of predefined reduction operations such as average(), sum(), min(), max(), and count(). These operations return a value by combining the elements of a stream.

What is significance of reduce () in Java?

Reducing is the repeated process of combining all elements. reduce operation applies a binary operator to each element in the stream where the first argument to the operator is the return value of the previous application and second argument is the current stream element.

What is identity in Reduce?

identity : Like the Stream. reduce operation, the identity element is both the initial value of the reduction and the default result if there are no elements in the stream. In this example, the identity element is 0 ; this is the initial value of the sum of ages and the default value if no members exist.

Is reduce a terminal operation Java?

A reduction is a terminal operation that aggregates a stream into a type or a primitive. The Java 8 Stream API contains a set of predefined reduction operations, such as average , sum , min , max , and count , which return one value by combining the elements of a stream.


2 Answers

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()
    .map(Object::toString)
    // or
    //   .map(x -> x.toString())  // exactly the same
    // or
    //   .map(String::valueOf)    // handles nulls by turning them to the string "null"
    .collect(Collectors.joining(","));

It has several overloads, similar to Scala's mkString. Still, this collector only accepts CharSequences, so you need to convert your values to strings explicitly as a separate map step.

Additionally, there is the String.join method, which also works for a collection of CharSequences. If you specifically have one of those (e.g. List<String>), it might be more convenient to use this method rather than converting the collection to a stream first:

List<String> strings = ...;

String result = String.join(",", strings);

// vs

String result = strings.stream().collect(Collectors.joining(","))
like image 151
Vladimir Matveev Avatar answered Sep 18 '22 22:09

Vladimir Matveev


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.

like image 23
Dima Avatar answered Sep 19 '22 22:09

Dima