

Why I absolutely love java - lfborjas
https://gist.github.com/817504
not
======
redthrowaway
I know it's fun to rag on Java, but this is a meaningless comparison. Java
isn't a scripting language, and it wasn't ever intended to be one. It was
never designed to solve quick little problems in a few lines, it was designed
to deal with massive enterprise apps with complicated dependency trees over
multiple architectures, and it does that job pretty damned well. Stop
complaining that Java isn't Python/Ruby. It's like saying that x86 assembly is
terrible because string concatenation takes so many loc.

Judging a language by standards it was never designed to meet is pointless. If
you want to decide whether Java is a good language or not, see if it solves
the problems it was designed to solve. I'd say it does. I may not like working
in Java for small projects, but that doesn't make it a bad language.

~~~
T_S_
I know it's fun to rag on Roman numerals, but they were never intended for
totaling receipts. They were never designed for quick little sums, they were
designed for engraving on massive long lasting objects like buildings and
copyright notices on feature films, and they look pretty darned good there.
Stop complaining that Roman numerals are not Arabic numerals. It's like saying
counting on fingers is terrible because nobody has more than X them (That's 10
to you youngsters, or 0b1010 to you real smart alecks).

Judging a numeral by a standard it was never designed to meet is pointless. If
you want to decide whether Roman numerals are a good number system or not, see
if you can hammer them onto a building. I'd say you can. I may not like
working with Roman numerals for grocery receipts, but that doesn't make them
bad.

~~~
MarkSimpson
> They were never designed for quick little sums, they were designed for
> engraving on massive long lasting objects like buildings and copyright
> notices on feature films, and they look pretty darned good there. Stop
> complaining that Roman numerals are not Arabic numerals.

Actually, Roman numerals were designed for counting the men in your army,
whereas Arabic numerals were designed for mathematics. Comparing the two isn't
a good argument against redthrowaway's point at all, because both are better
at the task they were designed for.

~~~
paradoja
?!?!?!?!?!

Are you saying that Roman numerals are better for counting than Arabic
numerals? I suppose you don't mean count (I, II, III, IIII, V...), but show
the number of men in the army. I don't see any advantage in using Roman
numerals.

Lets say we divide infantry in XXX maniples of CXX men each, supposing they
are complete and you haven't lost people yet in battle. How is that better
than 30 maniples of 120 men?

~~~
ent
Actually, roman numerals are easier to sum than arabics. To sum two roman
numerals you just write all the digits together and collapse them as much as
possible. There is no carrying over of digits and such.

Otoh, arabic numerals are a lot easier to multiply/divide. Before the wide
adoption of arabic numerals all but the most educated couldn't perform simple
multiplication/division.

~~~
paradoja
You may have a point, but I still find easier to do

    
    
             111
     948      948
     289  =>  289
     ---      ---
             1237
    

than

CMXLVIII plus CCLXXXIX => CMCCXLLXXXIXVIII => MCLLXXIXVIII => MCCXXXVII

but it may be that it's because what I'm used to.

------
sfraser
To be clear I <3 clojure, but I'm taking the bait just for fun:

1) The chunk of Java code shows a complete program - the others show function
definitions 2) The Java is written purposely to be as verbose as possible 3)
The Java sends it's output to stdout, unlike the others 4) The Java code is
needlessly written using generics

Things the comparison ignores: 1) The Java code is more toolable than the
others 2) The Java code will outperform most of the other examples once it has
been subject to Hotspot

Here's a more fair comparison, at the function level to level the playing
field (and only one import needed: java.util.*):

    
    
        List trollBait() {
            return new ArrayList(){{
                for (int i : new int[]{1, 2, 3, 4}) {
                    if (i % 2 == 0) add(i);
                }}};
        }
    

Here's why I absolutely do heart Java:

I just ran this 100,000 times in 6 milliseconds on a Core i7 920 (2.67 GHz).
And I scanned it with Findbugs, and PMD, and a security vulnerability tool.
And I refactored it in my IDE with crazy IntelliJ foo-jitsu. And it's more
strongly typed. And it's runtime memory model is safer.

~~~
lfborjas
now we're talking, this is a really good response! I almost agree with all of
your points, except for the performance, and only in thoroughness: a benchmark
will be nice.

And for clarity: the other ones aren't function definitions, they also build a
new list, like your example. The examples are meant to be run in a REPL and
that's why they don't send to stdout, although it will be just another
function application in most cases (but your example works in beanshell, the
stand-alone java quasi-REPL, so we're ok). I think all of them can be
considered a full-program in those languages: as a stand-alone chunk of code
that can be compiled/interpreted and will produce an executable output, that
is. And, yes, the autoboxing was the only reason I chose generics, but I tried
for it to be concise, given my limited knowledge of java; the max-verbose mode
would have used a Runnable or something evil to simulate a higher order
function.

~~~
sfraser
Thanks... my experience with clojure on the JVM is it is in general slower
than optimally tuned Java code. I really can't imagine that any of the other
languages you listed would easily outperform the code I have here, but maybe
since the use-case is a sweet spot for functional? The person who responded to
me with the F# example reported a crazy low time, and I am wondering if they
have a defect in the code. I think it is possible a true functional language
could make some tweaks that Java can't (like realizing the function is
idempotent and caching the response instead of recalculating it). Maybe that
is why the F# example was so quick - either the way it times itself is
defective, or perhaps the runtime memoizes the function.

My experience with all the languages in your sampler is that their runtime
performance usually lags the Java on the JVM for general purpose programming.
This is not an argument not to use them - I would prefer many of them in
certain use cases. But if I want a managed runtime, and have some performance
critical code that I am OK with being written in an imperative language, it is
hard to beat the performance of simple Java on the JVM. There has been so much
tuning to Hotspot over the last decade. That's been my experience anyways.

~~~
lfborjas
Interesting, and yes, I am a witness of how fast proper java is; and in
extreme performance cases, I guess I'd turn to java before C++ ; maybe the f#
also benefits from optimizations (like tail-call optimization) and the
underlying VM? (though I don't know how performant the CLR is)

------
blinkingled
If you want to love Java - love it for the tooling. IDEs are bloated but the
integrated features they provide - like built in profiler(Netbeans),
postmortem analysis tools (Eclipse MAT), the ease of debugging it provides -
remote attach, JConsole type stuff where you can visualize loads of
interesting stuff while the JVM is still executing your program, things like
EProf that comes with HP JVMs - it can be turned on and off dynamically with
low overhead and no changes required - the sort of data it gives makes it a
piece of cake to figure out what is going wrong (it even tells you during the
profile which exceptions were thrown and how many times!).

I make a living writing and supporting Enterprise Java apps and if it wasn't
for these rich set of tools, my job would have been a nightmare. (Before
flaming me saying if he wasn't writing code so badly in first place, he
wouldn't need those tools - I also support code written by other people and
writing complex, well performing code still remains notoriously hard.)

------
vilya
Here's a C++ 0x version, using a lambda function:

    
    
      #include <iostream>
      #include <algorithm>
    
      int main(int argc, char** argv) {
        int src[] = { 1, 2, 3, 4 };
        int* end = std::remove_if(src, src + sizeof(src) / sizeof(int),
            [](int i) -> bool { return i % 2 != 0; });
        for (int* p = src; p != end; ++p)
          std::cout << *p << " ";
        std::cout << std::endl;
      }
    

I wasn't sure about the lambda function syntax, but this compiles with g++ 4.5
(interestingly, even with the -Wall option, g++ doesn't warn about main not
returning a value). Shows that even c++ can be shorter than java...

~~~
serichsen
TL;DR

------
mike_esspe
Scala

    
    
      List(1, 2, 3, 4).filter(_ % 2 != 0)
    

And it's very easy to move to Scala from Java :)

------
julian37
This can be a lot shorter using Google Guava [1]:

    
    
            Collections2.filter(
                    Lists.newArrayList(1, 2, 3, 4),
                    new Predicate<Integer>() {
                        public boolean apply(Integer i) {
                            return i % 2 == 0;
                        }
                    });
    

As I understand it, JDK 8 will support lambdas which will make it shorter
still.

[1] <http://code.google.com/p/guava-libraries/>

~~~
shikyo
Or with <http://code.google.com/p/totallylazy/> (ignoring imports):

sequence(1,2,3,4).filter(even());

------
santadays

      import static com.google.common.collect.Lists.*;
      import static com.google.common.collect.Collections2.*;
      import com.google.common.base.*;
      public class AdmittedlyNotMuchBetter {
          public static void main(String[] args) {
            System.err.println(filter(newArrayList(1,2,3,4),new  Predicate<Integer>() { 
              public boolean apply(Integer input) {return input % 2 == 0;}
            }));
          }
      }
    

btw, how do you preserve source indentation in the comments? [edit:
formatting, thanks]

~~~
huherto
Had the same problem.

<http://news.ycombinator.com/formatdoc>

------
uvTwitch
C#: var filtered = (new int[]{1,2,3,4}).Where<int>( i => i%2 != 0 );

~~~
lars
This is what really shows the problem with Java.

~~~
zackb
And C#...

------
rlmw
\-- Haskell

filter even [1,2,3,4]

~~~
lfborjas
this looks really nice, gotta learn me some haskell

~~~
T_S_
You can. For free. Later this week in Mountain View. From some of the world's
best and friendliest Haskell experts.

<[http://wiki.hackerdojo.com/w/page/32992961/Haskell-
Hackathon...](http://wiki.hackerdojo.com/w/page/32992961/Haskell-
Hackathon-2011>);

Newbies take special note of the Saturday session.

------
nl
Screw that.

Others have already pointed out the Google Guava library. This version is
almost all just standard Java, just using Guava to create the list of numbers.

    
    
      ArrayList<Integer> list =  com.google.common.collect.Lists.newArrayList(1,2,3,4);
      for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) {if (it.next() % 2 == 0) {it.remove();}}		
      System.out.println(list);
    

Also, Java does have REPL. It's called the Eclipse scrapbook view. I'm sure
Netbeans has something similar (and that is part of one of the standard Java
SDK downloads).

~~~
fleitz
If you look close enough you can almost figure out what it's doing between all
the line noise.

~~~
nl

      // create an array list with 4 integer elements
      ArrayList<Integer> list =  com.google.common.collect.Lists.newArrayList(1,2,3,4); 
    
      // get an Iterator from the list, and use it to iterate though the list
      for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) {
        // check if this element is even. 
        // If we want the odd numbers, change to != 0 
        if (it.next() % 2 == 0) {
          // remove it if it is even
          it.remove();
        }
      }		
    
      // print the list
      System.out.println(list);

~~~
TeHCrAzY
Not sure if you were being a smart ass, but it would be much more readable
without any of the comments, and simply with the new lines.

~~~
nl
I'm being a smartass. Kinda..

The commenter said they could _almost figure out what it's doing_. It's not
clear from that that comment if it is just the formatting that was the problem
(which I agree, isn't very readable).

------
eldenbishop
\-- Groovy

    
    
      (1..4).findAll{!(it % 2)}

~~~
lfborjas
pretty cool!

------
dstein
You cheated. Do it without the fancy schmancy lists.

------
srgseg
Every time I see one of these ugly Java code examples, I always scratch my
head because my code never looks like this.

Here is what these code examples are exploiting:

1\. Java isn't designed for scripting. All of my Java programs require many
classes. I hardly have any main() methods because most things I write are
classes invoked by other classes, e.g. in the case of a servlet being invoked
by the web application server.

2\. It's rare in practice that I need to hard code the contents of data
structures inside my own code. Normally they are loaded from data files.

3\. Import statements are automatically thrown in by the IDE and most people
hardly even notice they're there and type nothing more than Alt-Enter any time
there is an import line missing.

So really, what I really am typing in java is only:

    
    
      List<Integer> result = new ArrayList<Integer>();
      for(int i : source) if(i%=2) result.add(i);
    

Now that's not really all that complicated is it?

~~~
djacobs
The point is that you have to write the for loop and if statement and
concatenation for each different function you want to define. The better way
is to use higher order functions, which Java lacks.

------
democracy
JAVA

for (int i:new int[]{1,2,3,4}) System.out.print(i%2==0?i:"");

~~~
lfborjas
hehe, clever! although we are building a new list in the other languages,
we're never using it, so this is just as good in the immediate context.

------
andralex
D rocks as usual: filter!`a % 2 == 0`(iota(1, 5)) (no eager computation, no
dynamic allocation)

------
zackb
Or you can just use groovy and get the best of both worlds :)
[1,2,3,4].findAll {it % 2 == 0}

------
ichramm
That's the problem of java developers, they dont use the bitwise operations:

if(e.intValue()%2 != 0) == >>> if((e.intValue()& 1) != 0)

~~~
jankassens
There's no problem here. You can be pretty sure simple calculations like this
(and multiplications with a power of 2 vs. shifting etc.) will run the same
machine code in the end.

~~~
sfraser
I think you are right in this case - I updated my example code above to use
bitwise and it is running in the same amount of time. (100,000 iterations in
about 6 milliseconds)

------
bitsai
I don't know about the other lisp dialects, but the anonymous function is
actually not needed in the Clojure version:

(filter even? [1 2 3 4])

~~~
vito
Same for the others.

    
    
        (filter even? '(1 2 3 4))
        (remove-it-not 'evenp '(1 2 3 4))

~~~
angus77
I think you mean 'remove-IF-not.

------
dekz
_coffeescript_

[1..4].filter (x) -> !(x%2)

------
earino
perl (because I feel like it):

grep { $_ % 2 == 0 } (1,2,3,4,5);

~~~
zakovyrya
even shorter: grep { $_ % 2 == 0 } 1..5;

------
djacobs
I used this exact example a few months ago to compare Java and Ruby [1]. Funny
how it keeps coming up.

(While I was using Java, I never even knew there was a need for higher-order
functions.)

[1] <http://news.ycombinator.com/item?id=1947723>

------
daleharvey
Erlang

    
    
        [X || X <- [1,2,3,4], X rem 2 == 0]

~~~
va_coder
umm is that supposed to show off Erlang? Maybe it's just me but for such a
simple task that looks bad.

~~~
daleharvey
it was just for completeness, certainly not to show off, however list
comprehensions are virtually identical to python and much more comprehensible
than the line noise introduced in ruby list comprehensions.

the fact that this is called out twice as being "ugly" twice in comparison to
the other examples auggests to me that erlang is called out as being ugly
purely from hearsay as opposed to actually being ugly.

(I do think erlang can be ugly, I also think thats its biggest strength, but I
dont think this example is ugly)

~~~
guygurari
_erlang is called out as being ugly purely from hearsay_

I have no preconceptions about Erlang. I've never seen the opinion that Erlang
is ugly, and your code above is the first Erlang I've ever seen. I also know
nothing about Haskell, but I found the Haskell example to be the most elegant.

So, a more reasonable conclusion: The fact that two people found the code ugly
suggests that it is ugly.

------
va_coder
What is Doug Cutting is saying these days about Java? He wrote Lucene, Hadoop
and other awesome things in Java. I don't like Java much but I'd love to hear
his side of the argument.

------
yakto
Job security?

------
huherto

      public class filter {
        public static void main (String [] args) {
          System.out.println("2, 4"); 
         }
       }
    

FTFY, While it may be fun that show off with your favorite language, the Java
version is intentionally complex.

Edit: In case you missed the point. This version is as absurd trying to be
short as the other version is absurd trying to be long. Also, I can guarantee
that an "Enterprise" version would be 200 lines long :-P

~~~
jbri
"Enterprise" developer at work here, folks!

------
rll
PHP

    
    
      array_filter(array(1,2,3,4),function($v) { return !($v&1); });

------
waterhouse
egrep:

    
    
      echo '1 2 3 4' | egrep -o '\<[0-9]*[02468]\>'

------
mitko
Advice, drop the 1 and 3: just [2,4] - its cleaner.

------
jules
J solution anyone?

~~~
losvedir

      &1/^@4%2!#
    

Just a guess...

------
fleitz
F#

    
    
      [1..4]
      |> List.filter(fun x ->  (x % 2) = 0)
    

C#

    
    
      using System.Collections.Generic;
       public static class Foo {
        public static void Main(string[] args){
          Enumerable.Range(1,4).Where(x => (x % 2) == 0); 
       } 
      }

------
foresterh
No C#?

~~~
mbthomas
Enjoy - <https://gist.github.com/817556>

~~~
kenjackson
In fairness to the Java version, you should probably add all the additional
stuff.

    
    
       using System.Linq;
       class Filter
       {
           static void Main()
           {
               var a = new []{1, 2, 3, 4}.Where(x=>x%2==0);
               System.Console.WriteLine(a);
           }
       }
    

It's unclear if printing is necessary or not, as the Java one does an explicit
print, but the others don't.

~~~
nrkn

      using System.Linq;
      class F {
        static void Main() {
          new[] {1, 2, 3, 4}.Where( i => i % 2 > 0 ).ToList().ForEach( 
            System.Console.WriteLine 
          );
        }
      }

~~~
TeHCrAzY
It's always irritated me that ForEach isn't available on IEnumerable<T>

