views:

373

answers:

11

Hi fellow Java programmers.

From the various online articles on Java 7 I have come to know that Java 7 will be having collection literals 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'.)?

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

Thanks.

A: 

yeah, it is the dumbest thing ever happening to java.

irreputable
I dunno about dumbest, I think type erasure might take that spot.
R0MANARMY
I "like" erasure.
Green Hyena
As in the band?
Fábio Batista
@Fábio LOL ... yes, exactly like the band
OscarRyz
+1  A: 

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.

DVK
+1  A: 

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.

Tom Cabanski
What is that you find so "flexible" in this syntax?
Green Hyena
A: 

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.

macbirdie
+2  A: 

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();
Geoff
Had they added tuples to Java (which would have been a much saner addition IMO), we could use this sort of syntax for `Map` initialization: `Map<String, String> capitals = HashMap.of(["India", "Delhi"], ["USA", "Washington DC"]);`
Green Hyena
+1  A: 

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...

kloffy
I like this example. So much cleaner and more readable than the Swing code in Java.
Green Hyena
That's possible in Java also. I don't know much about JavaFX, but if each of those elements were classes, you could type it like this: http://pastebin.com/jAqwXt7X
OscarRyz
@Oscar: Anonymous classes with instance initializer blocks. Neat trick! +1 :)
Green Hyena
@Oscar: That is a nice tick indeed, thanks for sharing!
kloffy
+1  A: 

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.

iPhone beginner
Umm... My question is why not `of` instead of these funny (IMO) syntaxes?
Green Hyena
These kind of syntax help **a lot** when you have to create fixtures for your tests for instance.
OscarRyz
Why not use "of"? The same reason: just save a bit of typing. There is main idea to express (creation of collection), and this seems to be the shortest way. The actual implementation of collection doesn't matter at all here. Collection and its data is the main thing. This save of a few characters is especially important if you want pass "inline" collection as argument to some method.
iPhone beginner
A: 

You are right this is just empty syntactic sugar.

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

Pyrolistical
+6  A: 

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.

Eric Eijkelenboom
Q3: Does it always have to be `final`?
Green Hyena
Re: `The compiler chooses a suitable implementation depending on the collection on the right-hand side.` --- When did compilers become so smart? (Some citations would be nice.)
Green Hyena
@Green Hyena: that is why I included the link, but I see that I linked to the wrong URL. This is now corrected. Thanks for hinting.
Eric Eijkelenboom
@Green Hyena: no, it does not have to be final. Immutable does not have anything to do with final, so that part could have been left out. Again, see the proposal.
Eric Eijkelenboom
Okay, thanks for the answer.
Green Hyena
A: 

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.

Alexander Pogrebnyak
http://ideone.com/vKab8 - This code doesn't give any warning.
Green Hyena
@Green Hyena: Instead of initializing it to `ArrayList< String >`, try to initialize it to `ArrayList<ArrayList< String >>`, then observe the warnings. If this sounds too far fetched, try to initialize `List< Class<?> >` without warnings.
Alexander Pogrebnyak
@Green Hyena: This is to demonstrate my point: http://ideone.com/WmgwT. BTW, +1 for showing this great tool.
Alexander Pogrebnyak
+3  A: 

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;
                     }};
                 }};
             };
         }};
     }};
 }};
OscarRyz
This (map.["name"]="Oscar";) just gave me a flashback to c++'s operator overloading.
David