Question

From the various online articles on Java 7 I have come to know that Java 7 will be having collection literals1 like the following:

List<String> fruits = [ "Apple", "Mango", "Guava" ];
Set<String> flowers = { "Rose", "Daisy", "Chrysanthemum" };
Map<Integer, String> hindiNums = { 1 : "Ek", 2 : "Do", 3 : "Teen" }; 

My questions are:

  1. Wouldn't it have been possible to provide a static method of in all of the collection classes which could be used as follows:

List<String> fruits = ArrayList.of("Apple", "Mango", "Guava");

IMO this looks as good as the literal version and is also reasonably concise. Why then did they have to invent a new syntax (EDIT: By 'new' I mean 'new to Java'.)?

  1. When I say List<String> fruits = [ "Apple", "Mango", "Guava" ]; what List would I actually get? Would it be ArrayList or LinkedList or something else?

1 As noted in the comments, collection literals did not make the cut for Java 7, nor indeed Java 8. (Here's an email from Brian Goetz, an Oracle developer, summarizing the rationale for not including this feature; and here is the proposal itself.)

Was it helpful?

Solution

Answer to question 2:

final List<Integer> piDigits = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9];

gives you an immutable list.

The whole idea of this proposal that the subtype cannot be specified. The compiler chooses a suitable implementation depending on the collection on the right-hand side.

Read the details here: Proposal: Collection Literals

Answer to question 1: yes it would have. It's a matter of style.

OTHER TIPS

Another thing to note is that for lists this is very easy using var args, but have a little think about how you'd do it for a map. There is no way to supply pairs of arguments to a var args method, unless you introduce an extra Map.Entry object or something like that.

So using existing syntax you'd end up with

Map<String,String> map = HashMap.of( new Entry( "key1", "value1" ), 
                                     new Entry( "key2", "value2" ) );

which would get very tiring very quickly.

Even if you go down the path of using a builder pattern (as we do) then it's pretty ugly

Map<String,String> map = CollectionUtil.<String,String>map()
                                        .put( "key1", "value1" )
                                        .put( "key2", "value2" )
                                        .map();

Not mentioned above is the simplicity of collections of collections. Lets say you want a constant to store the currency names and values of different countries.

// Currency devisions by country, and their various names
Map<String,Map<Float,List<String>>> CURRENCIES =
    { "US" : { 1 : ["dollar","buck"],
               0.25 : ["quarter"],
               0.10 : ["dime"],
               0.05 : ["nickel"],
               0.01 : ["penny"] },
      "UK" : { 1 : ["pound"],
               1.05 ["guinea"],
               0.125 : ["half crown"],
               0.05 : ["shilling","bob"],
               0.025 : ["sixpence"] } 
    };

I have pack an enormous amount of data in twelve extremely legible lines. Had I used ArrayList.of (ten times) and some similar map constructor (four times, with ten Map.EntryPair!), the function calls would have bloated the code and made it significantly harder to read.

While it is definitely in the domain of syntactic sugar, this is the #1 feature I'm looking forward to in Java 7 (if it ever gets out).

A1 Yes it is possible, but requires you to type more and more.

While this is not certainly something essentially wrong, it is one of the things developer complain more about. They ( and sometimes I do my self ) feel that Java is too verbose.

As the hardware got faster, new programming languages which at the beginning were too expensive to perform computations became feasible, and they are now being used more and more and are very popular. When developers have to type in Java again they feel, like oh no:, public static void main again! kind of.

One of the things that Java ( and statically types languages in general ) had to increase execution speed is to perform as many validations as possible before running ( that is, in the compiling stage )

These new programming languages ( remarkably Python and Ruby ) make a joy to program in, because you have to type less to achieve the same.

The reaction Java is taking to this, is to make the language bigger and incorporate some of this "syntactic sugar" into the language, that's why.

Even programming languages like C# had these extended features ( properties comes to my mind ) to make the developer code less.

At the end, I think these additions benefit the language, but they have to be added very carefully, to avoid break the compatibility and/or create a language that is so big, that nobody can use it.

I think an alternative would've been to allow the methods to be more expressive in their names, but that's very complicated, for Java. Perhaps in a new language :).

The Map put method signature could have been like this:

 /**
  * Analog to put( Object k, Object v );
  */
 public [( Object = k )]=( Object  v ) {
 } 

That's allow the method name be: [(key)]=(value) and eventually omit the parenthesis ( like in Ruby or originally in Smalltalk ) so this method would be:

 Map map = ....
 map.["name"]="Oscar";

Since that's not possible ( because []= are not valid method identifiers ) and writing:

 map.put("name","Oscar");

Is ... mmhh too verbose, they decided to add this solution.

Another enhancement are number literals, so you will be able to type:

 int million = 1_000_000;

A2 : You will get something else.

A3 ( expanding my comment on kloffy answer ).

You could write that same code in Java as of today.

Granted Stage, Scente, Group, Text, ImageView, Image were existing Java classes, you could type:

 new Stage() {{
     title  =  "Group-Nodes-Transformation";
     scene  =  new Scene() {{
         width =  600;
         height = 600;
         content = new Group() {{
             content = new Object[] =  {
                 new Circle() {{
                     centerX = 300;
                     centerY = 300;
                     radius = 250;
                     fill = Color.WHITE;
                     stroke = Color.BLACK;
                 }},
                 new Text() {{
                     x = 300;
                     y = 300;
                     content = "Mr. Duke";
                 }},
                 new ImageView() {{
                     image = new  Image() {{
                         url = "D:\\TEST\\Documents\\duke.png"
                         width = 50;
                         height = 50;
                     }};
                 }};
             };
         }};
     }};
 }};

They might have been inspired by the declarative programming style of JavaFX. If that is the case however, I'm disappointed that they didn't go all the way to support object literals as well. Here's an example of object literals in JavaFX:

Stage {
    title: "Group-Nodes-Transformation"
    scene: Scene {
        width: 600
        height: 600
        content: Group {
            content: [
                Circle {
                    centerX: 300
                    centerY: 300
                    radius: 250
                    fill: Color.WHITE
                    stroke: Color.BLACK
                },
                Text {
                    x: 300
                    y: 300
                    content: "Mr. Duke"
                },
                ImageView {
                    image: Image {
                        url: "D:\\TEST\\Documents\\duke.png"
                        width:50
                        height:50
                    }
                }
            ]
        }
    }
}

I think that this style of programming certainly lends itself to certain application areas. In the end it's always a matter of taste...

Language design is a matter of taste. Having said that, this kind of list/object initialization has become very popular. For example, C# has almost the same thing. The syntax is quite flexible and, as even your examples show, lets you initialize something like a dictionary inline. I rather like the syntax the designers chose here.

IMO this is just a Syntactic sugar that simplifies code a bit. Why are you not surprised by a sugar of the same kind:

int []arr1 = new int[] {1,2,3};
int []arr2 = {1,2,3};

It is just a convenient way to express a simple idea instead of writing something like

int []arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

Does this add something really new to our life? Well, no. Does it makes our lives a bit easier? I think, yes.

Regarding second part of question, I don't know what actual types would be. But frankly speaking, how often do you care what collection implementation is? Especially taking into account that such collections are expected to be relatively small (with all values typed by a developer). Anyway, in those rare cases when you do care, just don't use this simplified syntax and do the job yourself.

It's not entirely new syntax as such literals are present in Python, Javascript (json) and probably other languages.

I haven't seen any information on java 7 yet to be frank (were focused on C++ and Javascript lately), but it's actually good to see such an addition to the language.

Just to clarify one point - they did not "invent new syntax".

I'm not 100% sure where the original idea came from, but using "[]" to denote lists and "{}" to denote maps exists in Perl (where those are used in building array refs and hash refs).

There's no "set" in perl strictly speaking but the most idiomatic implementation of a set is a map (map set member to 1), so "{}" also fits.

So Perl would say exactly the same things as you listed as:

$fruits = [ "Apple", "Mango", "Guava" ]; # Creates array reference
$flowers = { "Rose" => 1, "Daisy" => 1, "Chrysanthemum" => 1 };
     # or { map {$_=>1} ("Rose", "Daisy", "Chrysanthemum"))
$hindiNums = { 1 => "Ek", 2 => "Do", 3 => "Teen" }; 

I'm not saying the above came from Perl, of course, but it is consistent with at least one other language and thus possibly with a wider use.

You are right this is just empty syntactic sugar.

Also your ArrayList.of(...) would be just short hand for new ArrayList<...>(Arrays.asList(...))

I think one of the reasons, is that of( ... ) will generate an unchecked warning if you would try to populate it with instances of generic objects.

The reason, ... expands to a java array, and java arrays do not like generic instances.

Here is an example from the spec that deals with this specific issue:

List<List<Integer>> pascalsTriangle =
    [[1],
     [1, 1],
     [1, 2, 1],
     [1, 3, 3, 1],
     [1, 4, 6, 4, 1]]

There is currently no way to initialize this variable in this concise manner and without unchecked warning.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top