Hacker News new | past | comments | ask | show | jobs | submit login
Java 7 - What's new? Release date, code examples and performance (inebium.com)
67 points by alrex021 on April 11, 2010 | hide | past | favorite | 26 comments



I'm wondering how the implementation is chosen when you do something like

  List<String> list = ["ham","eggs"];
Is it a linked list, an array list, a vector ... ?


The compiler chooses, probably based on the type and number of elements. In theory it should know how to do this efficiently, because this syntax returns only immutable collections, so the compiler knows up front exactly what the collection will ever contain.

This is what the proposal says about that decision:

  It is likely to be higher in space and time performance, in that the
  compiler can choose efficient implementations for small collections
  (such as empty collections and singletons).  On the other hand, it is
  less flexible, in that you cannot specify the implementation type.
From: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/0...


Why does it only return immutable collections? Because the spec says so, or because there is some principle suggesting that it should?

Personally, my first instinct was to read the syntax as a form of initialisation, not something that would bar me from adding or deleting elements after the set is instantiated.


Because it solves the problem mentioned above i.e. the compiler's choice of which type of container to create becomes straightforward.


If the choice would be a mutable one, making it expressly immutable after the fact serves no purpose. As it is, the compiler gets to choose an efficient list for the data provided, and then refuse to compromise on that efficiency later. You might as well use an enum. What useful collection implementation would require immutability? Even arrays are more flexible.

Sure, it's nice syntax, but I can come up with more scenarios where I'll want to initialize a collection than scenarios where I want to finalize one (well, excepting for the fact that this is java, where immutability is often considered a virtue).


How does this maintain the List interface, which defines methods for mutating the collection through methods such as add() and remove()?

If I get a variable of type List, I expect to be able to change the list.


The List interface labels all the methods that could change a list as "optional operation", which implementing classes are free to throw an UnsupportedOperationException for: http://java.sun.com/javase/6/docs/api/java/util/List.html

The current API already uses this in a bunch of places to return immutable Lists. For example, the lists you get out of Collections.singletonList() or Collections.nCopies() are immutable.

That's a bit broken from an OO perspective (is the interface an interface or not?), but it's a better solution than the const v. non-const container mess that C++/STL has, at least.


Good point. I see this as a good mechenism for allowing immutable lists (in which case it probably doesn't matter). But for mutable ones, you would probably want control over the datastructure.

The only way of allowing the programmer to do this, that I can think of for now, is by casting perhaps?

List<String> list = (LinkedList)["ham","eggs"];

Just an idea ...


List<String> list = new LinkedList<>(["ham","eggs"]);


Why you worry?


There's a lot of good stuff here--notably the (finally) decent support for literal sets, arrays, and maps in JSON style... but most importantly, closures! I am so sick and tired of creating one-off anonymous classes just to pass a function around. Unfortunately you can only use them with final variables. Ah, well...

http://blogs.sun.com/mr/entry/closures

http://blogs.sun.com/mr/entry/closures


The top priority is still to avoid confusing programmers, and closing over non-final variables can lead to some very confusing situations. For example:

List list = Lists.newArrayList(); for(Integer i = 0; i < 10; i++) { list.add(fn [x] { i + x }); }

Think you just created a list of 10 functions that each add a different number to their argument? If you closed over the i variable, that variable changed and by the end of the loop is 9. All of the functions return their argument plus 9.

In any case, I can't wait to get some form of closures in Java. Best case would be to get a job using a decent programming language, but closures and various data type literals could go a long way to dull the pain until then.


This certainly does appear to be a common point of confusion for languages that have both mutable variables and closures:

http://stackoverflow.com/questions/271440/c-captured-variabl... http://stackoverflow.com/questions/233673/lexical-closures-i...

I remember bumping into the issue myself in JavaScript, but only once. After I became aware of the concept, it was never a problem again, in any language. Those one-time issues don't worry me. It's the problems that come up over and over again that are worth fixing at the language level.

A good way to explain it is to analogize captured variables to variables used in the body of a loop or conditional. Variables are only ever created when a declaration is evaluated, and a variable has exactly one value at any given time. The obvious alternative, copying the variable when it's closed over, seems more confusing to me. And the current restriction, that captured variables are final, is just going to force hackery.

Ultimately, if Java grunts want closures, they will have to understand variable capturing. It's part of the package.


To me the confusion is more with the loop constructs. My mental model is fine with variable capture in general, but I don't interpret loop variables as "real" variables. What I'd intuitively expect, if I didn't already know that most languages don't do it that way, is that the loop variable is freshly bound on each iteration. That expectation is strengthened by the fact that a lot of languages seem not to want to allow you to actually use it as a real variable anyway: you often can't modify the loop variable within a foreach-style loop, which leads me to view them as fresh immutable bindings per iteration.

Admittedly, the Java for loop is a plain C-style for loop, where you actually can modify the loop variable if you wish, so it pretty much has to work that way. But the binding-reuse behavior of, say, Python's for i in range(n) loop makes less sense to me. IIRC, it's also one of the many contentious differences in Common Lisp between the LOOP and ITERATE macro packages.


Ah yes, it is a problem if a language is not clear about the lifetime semantics of a loop variable.

In Ruby, for example, an idiomatic loop like 10.times{|i| ... } does indeed bind a new variable for every iteration, but that is implicitly clear to anyone with a basic understanding of the language. Likewise, the 3-part for loop of Java et al does not hide the fact that it's the same variable every time through the loop.

The Java for-each loop, on the other hand, is more ambiguous. A quick check seems to indicate that the iterator variable can be declared final and captured in an anonymous inner class. That means that for-each acts differently than for loop and I could see that confusing your average code monkey.


Yeah, I think the main thing that's confusing about the particular example given in this thread is that the common case of looping over integers usually intends a foreach-style loop, but Java syntax doesn't make it easy to do something like for(final int i : Range(1,10)). So people end up using the C-style 3-part for loop when they don't have any real need for its power.


I actually think that will change in Java 7. I will likely not be using "for" very often, and will start using higher-order functions like map and fold. The issue is mainly developers for whom closures are a new concept. If they are too confused as they make their first nervous steps into the world of functional programming, if their first attempts at using closures result in a lot of bugs, then they may write off the whole thing as more complicated than it's worth.


If you cannot wait for Java 1.7, use usual trick with anonymous classes and static initializer block:

  Java 1.7:
  List<String> list = ["item"];

  Java 1.2:
  List<String> list = new AList<String>() {{ items=["item"]; }};
where:

  public class AList<T> implements List<T> {
    protected T[] items;
    // Implementation
 }

  Set<String> set = {"item"};
  Set<String> set = new ASet<String>() {{ items={"item"}; }};

  Map<String, Integer> map = {"key" : 1};
  Map<String, Integer> map = new AMap<String, Integer>() {{ keys=["key"]; values=[1]; }};

I can post detailed explanation and examples of this technique, which I love to use, in my blog, if somebody will be interested. (English is foreign language to me).

It is much better than to use full blown implementation and bunch of setters just to pass around one or two elements.

I often use this technique to pass optional data to/from methods or to program in declarative style in java.


For lists, you can also do this: List<String> strings = new ArrayList<String> (Arrays.asList("one", "two", "three"));


Yes, you right. This is very cheap way to initialize ArrayList. I use it too.

Did you know something similar for Map's? :-)


Unfortunately, no.


Or use Google Collections in Java 1.5 or higher.

http://code.google.com/p/google-collections/

List<String> list1 = Lists.newArrayList("item"); List<String> list2 = Lists.newArrayList("item1","item2");

Of course, none of these workarounds are close to what Java 7 offers. Just a few more months :-)


> Or use Google Collections in Java 1.5 or higher.

See Sandman reply.


I'm guessing the same applies for C#, does anyone know if there are language supported features for lists like the new java ones for C#?


[deleted]


I would read it.


Where can I go for more benchmarks?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: