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.
> It was designed to deal with massive enterprise apps with complicated dependency trees over multiple architectures
Actually it was designed to run on washing machines, refocused to work for browser applets, and then refocused again to deal with massive enterprise apps. I'm not sure it was ever suited to any of those tasks -- it's merely has a good enough cross section of features. One only has to look over at what Microsoft has done with C# to see that Java could be significantly less verbose.
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.
It's perfectly reasonable to rag on it for this. What's not reasonable is that the code can be written in a much more compact way by not trying for an "applicative" style.
List even = new ArrayList();
for(int i : new Integer[]{1,2,3,4})
if (i%2==0) even.add(i);
Still larger than necessary, and this doesn't have all the necessary class cruft, but still much smaller.
Where it all went wrong was when someone said Java is what the web should be developed with, we then got JSP, servlets and later Struts. Java web was brain dead on arrival and thankfully new style development trends are rectifying that evil. With JavaScript and Mobile apps taking over the UI from Java (as well as the other web frameworks for that matter), it becomes evident that Java when weighed in the balance is not that wanting, sure it does not do some things well and it can be a bit verbose, but as a back end language, I see no reason to abandon Java for purely technical merits. I do have concerns about Oracle's stewardship but that is another topic for another day.
However, since Java was not intended to be a scripting language, then it should never have monopolized the material of introductory programming classes like it did. I consider Java to be a very ungentle introduction to programming when compared with Python, Ruby or Scheme.
Sorry to be pedantic, but wasn't Java designed initially for set-top boxes, when it was still called Oak, and was repeatedly re-purposed for running code in web pages (as applets) and then for enterprise-friendly server-side web apps (J2EE)?
> Java isn't a scripting language, and it wasn't ever intended to be one.
First class functions aren't a feature particular to scripting languages. Many compiled languages also have them, such as Haskell, Ocaml, Scala, F#, C#, D, Go, Forth, Common Lisp, and so on.
> It was never designed to solve quick little problems in a few lines
C# wasn't either, but it manages to be pretty expressive for what it is. I don't think you can argue Java's design precludes it from having basic things like first class functions, when (a) C# operates in the same market and already has them, and (b) Java 7 is going to be getting them.
Oh, this is just a tongue-in-cheek joke; java has really cool stuff, I actually code in java every morning and I really like the JVM and the JIT, without it, clojure, jruby and jython wouldn't exist, and jruby is way cooler than Cruby!
You're right, we can't be saying that a language sucks because it doesn't look cool in some coding styles. Is like trying to do fancy OOP in pure scheme or common lisp without the CLOS!
This is not a meaningless comparison; it points out one of the main deficiencies of java: lack of first-class functions. The closest you can come is using anonymous inner classes, which is kind of kludgy.
I completely agree, though this is where I take issue with both the Java community and with managers and architects who have pushed for Java to be standard outside of the enterprise realm. I don't hate the language, I dislike the people who try to fit the square plug into the round hole. It's taking a lot of explaining to a lot of people at my workplace/university (a Java school naturally) that when developments teams are segregated into 1/2 person teams, have high turnover, and spread widely across an organization, using Java just doesn't make sense. It makes a lot more sense to use an easily approach scripting language such as Python or PHP in this case. But yet I had several Java evangelists literally screaming at me over our decision to go with PHP. In the end we won out, we built a solution that has run flawlessly (knock on wood) and the Java evangelists were moved to other departments.
Filtering a list of numbers by a criterion is not a standard. It's a simple task. The discussion does have relevance - it shows why Java programmers need to rely so heavily on cookie cutter libraries: writing something from scratch is a huge bear.
I routinely interview programmers of all kinds. Extremely few Java programmers ever make it because they simply don't know how to get simple (but non-mainstream) algorithmic tasks done.
> Java isn't a scripting language, and it wasn't ever intended to be one.
One of my beliefs is that we shouldn't think about "scripting languages" versus "compiled languages" and just think in terms of what would make for the ideal programming language, period. By that standard, Java is inferior to Python (to pick just one example) because it is so much more verbose and formal when accomplishing the same desired task.
Actually judging a language by standards it was never designed to meet is not pointless. I judge languages by how well they solve problems I need to solve. I don't care if it was intended to solve that problem.
Generally, typing extra stuff to make my code work isn't one of the problems I have.
x86 assembly IS terrible because string concat takes many loc. I use x86 assembly to solve problems where speed is paramount, string concatenation generally isn't one of those problems. Like lets say you need to reformat a little endian RGB pixel into a big endian RGB pixel, then that's something I'd use assembly for.
Java as a language is horrible language because the only problem it solves well is how to inflate a consulting bill, or how to waste developers time figuring out what exceptions a method throws. Only exception a method needs to throw is JavaOutTheDoor.
Solving a problem in java is like winning a race where your legs are hobbled, yes, it's an accomplishment, but wouldn't it have just been smarter to untie your legs? Java was invented in 1994 or something like that, and the scary part is it hasn't changed. Perhaps I should still code my C K&R style?
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.
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.
That's not bad, how about 0.014 milliseconds for 100,000 iterations? On a Core i5 @ 2.6 Ghz
// Learn more about F# at http://fsharp.net
open System
let consume x = ()
let start = System.Environment.TickCount
Seq.init 100000 id
|> Seq.iter (fun x -> [0..4] |> List.filter (fun y -> (y % 2) = 0) |> consume )
let endTime = System.Environment.TickCount
printfn "%f milliseconds" (TimeSpan.FromTicks(int64(endTime - start)).TotalMilliseconds)
Output:
0.014100 milliseconds
Press any key to continue . . .
I'm sure if I added some java line noise I could get it up to 6 milliseconds. Too bad I didn't need a calendar class to figure out how to get from ticks to milliseconds. It's also really unfortunate that System.Environment.TickCount compiles down to a single assembly instruction. I was really hoping to use a factory pattern in there somewhere. Maybe some IOC containers. What good is a language if you can't write half your code in XML.
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.)
#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...
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).
The lack of closures is seriously felt when creating the "isEven" Predicate. This will be a lot cleaner next year (?), when closures are introduced in the language. For now, we have to live with the verbosity...
It's possible to hide some of this verbosity and write clean code. For example, I often extract the function / predicate declarations to utility classes to avoid polluting the code. In this case, I would move the "isEven()" method to a "MathPredicates" utility class. The code ends up looking like:
List<Integer> list = newArrayList(1,2,3,4);
System.out.println(Iterables.filter(list, MathPredicates.isEven()));
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);
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.
[+] [-] redthrowaway|15 years ago|reply
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.
[+] [-] wvenable|15 years ago|reply
Actually it was designed to run on washing machines, refocused to work for browser applets, and then refocused again to deal with massive enterprise apps. I'm not sure it was ever suited to any of those tasks -- it's merely has a good enough cross section of features. One only has to look over at what Microsoft has done with C# to see that Java could be significantly less verbose.
[+] [-] T_S_|15 years ago|reply
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.
[+] [-] pmarin|15 years ago|reply
Actually it was originally designed for embedded system with limited resources [1].
[1] http://www.oracle.com/technetwork/java/javase/overview/javah...
[+] [-] wnoise|15 years ago|reply
Stolen shamelessly from https://gist.github.com/817635
[+] [-] kls|15 years ago|reply
[+] [-] evanrmurphy|15 years ago|reply
However, since Java was not intended to be a scripting language, then it should never have monopolized the material of introductory programming classes like it did. I consider Java to be a very ungentle introduction to programming when compared with Python, Ruby or Scheme.
[+] [-] umjames|15 years ago|reply
[+] [-] weavejester|15 years ago|reply
First class functions aren't a feature particular to scripting languages. Many compiled languages also have them, such as Haskell, Ocaml, Scala, F#, C#, D, Go, Forth, Common Lisp, and so on.
> It was never designed to solve quick little problems in a few lines
C# wasn't either, but it manages to be pretty expressive for what it is. I don't think you can argue Java's design precludes it from having basic things like first class functions, when (a) C# operates in the same market and already has them, and (b) Java 7 is going to be getting them.
[+] [-] lfborjas|15 years ago|reply
You're right, we can't be saying that a language sucks because it doesn't look cool in some coding styles. Is like trying to do fancy OOP in pure scheme or common lisp without the CLOS!
[+] [-] bdj|15 years ago|reply
[+] [-] nowarninglabel|15 years ago|reply
[+] [-] andralex|15 years ago|reply
I routinely interview programmers of all kinds. Extremely few Java programmers ever make it because they simply don't know how to get simple (but non-mainstream) algorithmic tasks done.
[+] [-] mkramlich|15 years ago|reply
One of my beliefs is that we shouldn't think about "scripting languages" versus "compiled languages" and just think in terms of what would make for the ideal programming language, period. By that standard, Java is inferior to Python (to pick just one example) because it is so much more verbose and formal when accomplishing the same desired task.
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] fleitz|15 years ago|reply
Generally, typing extra stuff to make my code work isn't one of the problems I have.
x86 assembly IS terrible because string concat takes many loc. I use x86 assembly to solve problems where speed is paramount, string concatenation generally isn't one of those problems. Like lets say you need to reformat a little endian RGB pixel into a big endian RGB pixel, then that's something I'd use assembly for.
Java as a language is horrible language because the only problem it solves well is how to inflate a consulting bill, or how to waste developers time figuring out what exceptions a method throws. Only exception a method needs to throw is JavaOutTheDoor.
Solving a problem in java is like winning a race where your legs are hobbled, yes, it's an accomplishment, but wouldn't it have just been smarter to untie your legs? Java was invented in 1994 or something like that, and the scary part is it hasn't changed. Perhaps I should still code my C K&R style?
[+] [-] sfraser|15 years ago|reply
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.*):
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|15 years ago|reply
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.
[+] [-] va_coder|15 years ago|reply
[+] [-] fleitz|15 years ago|reply
[+] [-] blinkingled|15 years ago|reply
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|15 years ago|reply
[+] [-] serichsen|15 years ago|reply
[+] [-] mike_esspe|15 years ago|reply
[+] [-] julian37|15 years ago|reply
[1] http://code.google.com/p/guava-libraries/
[+] [-] shikyo|15 years ago|reply
sequence(1,2,3,4).filter(even());
[+] [-] democracy|15 years ago|reply
[+] [-] santadays|15 years ago|reply
[+] [-] huherto|15 years ago|reply
http://news.ycombinator.com/formatdoc
[+] [-] rst|15 years ago|reply
[+] [-] uvTwitch|15 years ago|reply
[+] [-] rlmw|15 years ago|reply
filter even [1,2,3,4]
[+] [-] nl|15 years ago|reply
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.
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).[+] [-] eneveu|15 years ago|reply
It's possible to hide some of this verbosity and write clean code. For example, I often extract the function / predicate declarations to utility classes to avoid polluting the code. In this case, I would move the "isEven()" method to a "MathPredicates" utility class. The code ends up looking like:
[+] [-] andralex|15 years ago|reply
[+] [-] fleitz|15 years ago|reply
[+] [-] eldenbishop|15 years ago|reply
[+] [-] dstein|15 years ago|reply
[+] [-] srgseg|15 years ago|reply
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:
Now that's not really all that complicated is it?[+] [-] democracy|15 years ago|reply
for (int i:new int[]{1,2,3,4}) System.out.print(i%2==0?i:"");
[+] [-] lfborjas|15 years ago|reply
[+] [-] andralex|15 years ago|reply
[+] [-] zackb|15 years ago|reply
[+] [-] ichramm|15 years ago|reply
if(e.intValue()%2 != 0) == >>> if((e.intValue()& 1) != 0)
[+] [-] jankassens|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] bitsai|15 years ago|reply
(filter even? [1 2 3 4])
[+] [-] vito|15 years ago|reply
[+] [-] dekz|15 years ago|reply
[1..4].filter (x) -> !(x%2)