4

Here are 2 code snippets, which are supposed to return the same result, as I used HashMap in map factory. But the second code snippet doesn't compile in IntelliJ. Both codes work fine in Eclipse.

System.out.println method required something where it can call toString, but in IntelliJ I get this weird error, Why ?

Compileable code (both Eclipse & IntelliJ):

 System.out.println(Arrays.stream(str.split(" "))
                          .collect(Collectors.groupingBy(
                                                  Function.identity(), 
                                                  Collectors.counting())));

Erroneous Code (works in Eclipse but fails only in IntelliJ):

  System.out.println(Arrays.stream(str.split(" "))
                            .collect(Collectors.groupingBy(
                                                       Function.identity(), 
                                                       HashMap::new, 
                                                       Collectors.counting())));

The error for second snippet in IntelliJ

Required type: String
Provided: Map

<java.lang.String,java.lang.Long> no instance(s) of type variable(s) K, V exist so that HashMap<K, V> conforms to String
howlger
  • 31,050
  • 11
  • 59
  • 99
ThrowableException
  • 1,168
  • 1
  • 8
  • 29
  • 3
    This code works fine for me with no errors. – Ravindra Ranwala Jan 12 '20 at 04:12
  • Thanks for pointing it out... After your comment, I tried the same code in eclipse and it works. but in IntelliJ, it doesn't even compile. I'll rephrase my question to ask wy it doesn't work in IntelliJ but work in eclipse. – ThrowableException Jan 12 '20 at 04:34
  • Please post a complete minimal example reproducing the problem, along with the exact and complete error you get from the compiler. – JB Nizet Jan 12 '20 at 07:10

1 Answers1

5

That seems a bug of javac which is used by IntelliJ IDEA. In contrast, Eclipse has its own compiler.

It fails with javac of Java 8 and 11, but if the collector in collect(...) is extracted to a var variable (available since Java 10) than it compiles without errors with javac of Java 11:

var collector = Collectors.groupingBy(Function.identity(),
                                      HashMap::new,
                                      Collectors.counting());
System.out.println(Arrays.stream(str.split(" ")).collect(collector));

Hence, the collector type can be inferred and used here.

As workaround for javac, you can use the following code for Java 8 where var is not available:

Collector<Object, ?, Map<Object, Long>> collector =
                Collectors.groupingBy(Function.identity(),
                                      HashMap::new,
                                      Collectors.counting());
System.out.println(Arrays.stream(str.split(" ")).collect(collector));
howlger
  • 31,050
  • 11
  • 59
  • 99
  • I'd say that, because Eclipse is using a non-standard compiler, the issue lies with Eclipse as opposed to IntelliJ. Eclipse compiler issues are fairly well documented, and this is one of those quirks. – Makoto Jan 12 '20 at 17:53
  • 4
    @Makoto What is wrong and right is defined by the [Java Language Specifications](https://docs.oracle.com/javase/specs/), not by a standard implementation. – howlger Jan 12 '20 at 18:01
  • 1
    Yes, and this is why it's easier to [blame Eclipse's compiler](https://stackoverflow.com/q/3061654/1079354) because it **doesn't** follow the spec as strictly as javac. – Makoto Jan 12 '20 at 18:13
  • 3
    @Makoto that's wrong too. The Eclipse compiler for Java is Java-certified (otherwise it cannot even be called a "compiler for Java" as usage of Java is protected by trademarks that require certification to be used). So it's conform to the spec, as strictly as the spec is defined. Maybe there are holes in the spec that can leave room for divergence, but still, assuming Eclipse compiler is wrong because it's not javac is a major mistake in the understanding of how spec/certification work in Java world. – Mickael Jan 12 '20 at 20:58
  • For the sake of completeness of the answer: in IntelliJ IDEA you can switch the compiler to Eclipse compiler (from default `javac`) in Settings (Preferences on macOS) | Build, Execution, Deployment | Compiler | Java Compiler | **Use compiler** and set it to **Eclipse**. – Andrey Jan 13 '20 at 07:21