Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing Opportunities with Java Streams

I was looking through some code and came across this method that takes an HTML Header value (i.e. Content-Disposition=inline;filename=foo.bar) and parses it into a map separated by the semi-colon's into key=value pairs. At first it looked like a good candidate for optimization using a stream, but after I implemented it, the fact that I can't reuse the computed String.indexOf('=') value means the string must be scanned 3 times, which is actually less optimal than the original. I'm perfectly aware that there are many instances where Streams aren't the right tool for the job, but I was wondering if I had just missed some technique that could allow the Stream to be as performant/more performant than the initial code.

  /**
   * Convert a Header Value String into a Map
   *
   * @param value The Header Value
   * @return The data Map
   */
  private static Map<String,String> headerMap (String value) {
    int eq;
    Map<String,String> map = new HashMap<>();
    for(String entry : value.split(";")) {
      if((eq = entry.indexOf('=')) != -1) {
        map.put(entry.substring(0,eq),entry.substring(eq + 1));
      }
    }
    return map;

    return Stream.of(value.split(";")).filter(entry -> entry.indexOf('=') != -1).collect(Collectors.));
  } //headerMap

My attempt at Streaming it:

  /**
   * Convert a Header Value String into a Map
   *
   * @param value The Header Value
   * @return The data Map
   */
  private static Map<String,String> headerMap (String value) {
    return Stream.of(value.split(";")).filter(entry -> entry.indexOf('=') != -1).collect(Collectors.toMap(entry -> entry.substring(0,entry.indexOf('=')),entry -> entry.substring(entry.substring(entry.indexOf('=') + 1))));
  } //headerMap
like image 570
TheChrisPratt Avatar asked Sep 01 '15 20:09

TheChrisPratt


People also ask

Is Java stream optimized?

Java 8 Streams API optimises stream processing with the help of short circuiting operations. Short Circuit methods ends the stream processing as soon as their conditions are satisfied.

What is the performance benefit of using streams?

There are a lot of benefits to using streams in Java, such as the ability to write functions at a more abstract level which can reduce code bugs, compact functions into fewer and more readable lines of code, and the ease they offer for parallelization.

What are the 3 types of streams in Java?

Java provides three predefined stream objects: in, out, and err, defined in the System class of the java.

What are Java streams used for?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.


1 Answers

This solution looks for '=' only once:

private static Map<String, String> headerMap(String value) {
    return Stream.of(value.split(";"))
            .map(s -> s.split("=", 2))
            .filter(arr -> arr.length == 2)
            .collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
}

Note that here the fast-path for String.split is used, thus regular expression is not actually created.

Note that using Guava you can do this in quite clean way even prior to Java-8:

private static Map<String, String> headerMap(String value) {
    return Splitter.on( ';' ).withKeyValueSeparator( '=' ).split( value );
}

In general I would advise you against manual parsing of HTTP headers. There are many caveats there. See, for example, how it's implemented in Apache HTTP library. Use libraries.

like image 120
Tagir Valeev Avatar answered Oct 21 '22 02:10

Tagir Valeev