java: Arrays.sort() with lambda expression
Asked Answered
F

4

35

I want to sort String elements in the array months by length using Arrays.sort method. I was told here, that it's possible to use lambda expressions instead of creating new class implementing Comparator. Did it exactly the same way, yet it doesn't work.

import java.util.Arrays;
import java.util.Comparator;

public class MainClass {
public static void main(String[] args)
{

    String[] months = {"January","February","March","April","May","June","July","August","September","October","December"};

    System.out.println(Arrays.toString(months)); //printing before


    //neither this works:
    Arrays.sort(months, 
            (a, b) -> Integer.signum(a.length() - b.length())   
    );

    //nor this:
    Arrays.sort(months, 
            (String a, String b) -> { return Integer.signum(a.length() - b.length()) }; 
    );


    System.out.println(Arrays.toString(months)); //printing after
}
}
Filide answered 23/2, 2014 at 16:7 Comment(2)
"Did it exactly the same way, yet it doesn't work." No you didn't, read carefully what they did. You have syntax errors.Stagehand
@ZouZou Perhaps he did. I don't think the OP is even using Java 8.Glower
V
87

The cleanest way would be:

Arrays.sort(months, Comparator.comparingInt(String::length));

or, with a static import:

Arrays.sort(months, comparingInt(String::length));

However, this would work too but is more verbose:

Arrays.sort(months,
            (String a, String b) -> a.length() - b.length());

Or shorter:

Arrays.sort(months, (a, b) -> a.length() - b.length());

Finally your last one:

Arrays.sort(months, 
    (String a, String b) -> { return Integer.signum(a.length() - b.length()) }; 
);

has the ; misplaced - it should be:

Arrays.sort(months, 
    (String a, String b) -> { return Integer.signum(a.length() - b.length()); }
);
Vandenberg answered 23/2, 2014 at 16:15 Comment(11)
+1 for showing Comparator.comparing, it is so much easier to grasp than writing a custom lambda or Comparator.Paramedic
Well, that's helpful, but I'd like to know what's wrong with my solution.Filide
@lavsprat I have added something showing your syntax error.Vandenberg
I suggest using Integer.compare instead of signum of -.Hedgehop
@PeterLawrey Indeed - signum(a-b) has the risk of overflowing (even if it's unlikely for strings).Vandenberg
@lavsprat Then you don't have java 8 installed or you are not compiling with the right JDK or your IDE does not support it or you have a very old version or...Vandenberg
Oracle site says "You have the recommended Java installed (Version 7 Update 51).".Filide
@lavsprat huh.... Version 7 != Version 8... Java 8 is here: jdk8.java.net/download.htmlVandenberg
I don't think - can overflow in this case, as both values are non-negative.Gat
Integer.signum is obsolete. Just returning a-b (for these special a and b where a-b cannot overflow, of course) is enough. There is no need to set the absolute value to 1. So wrapping a value which has the right sign already with an Integer.signum(…) call makes no sense for a Comparator.Capers
I certainly prefer Comparator.comparingInt() over comparing() when what you are comparing are indeed ints. It’s clearer (and also avoids unnecessary boxing).Virus
G
3

You're looking for this:

Arrays.sort(months, (a, b) -> Integer.signum(a.length() - b.length()));
Glower answered 23/2, 2014 at 16:14 Comment(4)
Works for me... Are you sure you're using Java 8? Which IDE are you using?Glower
@lavsprat It also works for me, it prints [May, June, July, March, April, August, January, October, February, December, September]... What Java 8 version are you using?Paramedic
I'm using Eclipse. This site says I have Version 7 Update 51.Filide
Well of course you can't use lambdas then, as they are only available in Java 8.Glower
O
2

The functionality you are looking for is in Java 8, which has not yet been released. It is scheduled for release in a few months if you want to wait, or if not beta downloads are available.

Object answered 23/2, 2014 at 16:35 Comment(4)
Useful comment, but not an answer.Unbrace
@TedHopp It is an answer. His code isn't compiling because he's trying to use a Java 8 feature in Java 7!Object
His code isn't compiling because it has a syntax error (semicolon at the end of the second argument to Arrays.sort).Unbrace
This comment is a bit misleading, unless you count three weeks as being "a few months": ship date is March 18thHysteria
C
0

You can try this:

Arrays.sort(months, (a,b) -> Integer.compare(a.length(), b.length()));
Cessionary answered 9/8, 2023 at 15:3 Comment(1)
Note that Integer#compare doesn't state it, but the return value is always -1, 0, or 1 (whereas the javadoc implies it's merely <0 or >0, so it is subject to change). #signum explicitly states this relationship. Either way, for Arrays#sort, I don't see what this answer contributes that the others didn't already cover 9 years ago.Ruthy

© 2022 - 2024 — McMap. All rights reserved.