Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8016702

use of ternary operator in lambda expression gives incorrect results

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 8
    • 8-repo-lambda
    • tools
    • b100
    • Verified

      Consider the following code:

      public class Ternary {
          public static void main(String[] args) {
              List<String> list = Arrays.asList("one", null, "three");
              domap(1, list, s -> (s == null) ? "*NULL*" : s);
              domap(2, list, s -> (s != null) ? s : "*NULL*");
              domap(3, list, s -> (String)((s == null) ? "*NULL*" : s));
              domap(4, list, (String s) -> (s == null) ? "*NULL*" : s);
              domap(5, list, s -> ((s == null) ? "*NULL*" : s));
              domap(6, list, s -> (s == null) ? "*NULL*" : ((String) s));
              domap(7, list, s -> (s == null) ? s : "*NON-NULL*");
              domap(8, list, s -> ((String)s == null) ? "*NULL*" : s);
              domap(9, list, (Function<String,String>)s -> (s == null) ? "*NULL*" : s);
          }
          
          public static <T,R> void domap(int n, List<T> list, Function<? super T,? extends R> mapper) {
              System.out.printf("-- %d --%n", n);
              list.stream()
                  .map(mapper)
                  .forEach(s -> System.out.println(s));
          }
      }

      The expected output is

      one
      *NULL*
      three

      but in cases 1, 4, 5, 6, and 8 the output is

      *NULL*
      *NULL*
      *NULL*

      The problem seems to have something to do with type inferencing, since it is can be influenced by putting a cast in the right place. But the behavior is hard to explain.

      Note that the inferencing for domap() is not relevant to the issue; that's just in the test code to provide a convenient framework to test a bunch of cases that vary only slightly. The following simplified example also shows the incorrect behavior of printing *NULL* three times:

      public class Ternary2 {
          public static void main(String[] args) {
              Arrays.asList("one", null, "three")
                    .stream()
                    .map(s -> (s == null) ? "*NULL*" : s)
                    .forEach(s -> System.out.println(s));
          }
      }

      This occurs in Lambda b92.

            mcimadamore Maurizio Cimadamore
            smarks Stuart Marks
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: