Xiaoyu Yuan
Xiaoyu Yuan

Reputation: 29

How to use lambda expression to call the comparator?

I am doing the leetcode's largest Number problem. Here is the problem:

Given a list of non negative integers, arrange them such that they form the largest number.

For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.

and there is a 5 lines C# code:

internal static string LargestNumber(List<int> vals)
    {
        if(vals==null || vals.Count==0)
            return "";
        vals.Sort((a,b)=>String.Compare(b+""+a,a+""+b));
        return vals[0]==0?"0":String.Join("",vals);
    }

it uses the lambda expression. But when I tried to write the java code:

public String largestNumber(int[] num) {
  String[] sNum = new String[num.length];
    for(int i = 0;i<num.length; i++){
        sNum[i] = Integer.toString(num[i]);
    }
    Collections.sort(sNum,(String n1,String n2) -> (n1 + n2).compareTo(n2 + n1));
    String s = sNum[0];
    for(int i = 1;i<sNum.length;i++)
        s += sNum[i];
    if(s.charAt(0) == '0')
        s = "0";
    return s;
}

it reports the error: Multiple markers at this line - Type mismatch: cannot convert from Comparator to Comparator - The method sort(List, Comparator) in the type Collections is not applicable for the arguments (String[], (String n1, String n2) -> {})

could anyone help me about this lambda expression problem in java?

Upvotes: 0

Views: 1065

Answers (5)

Holger
Holger

Reputation: 298539

In Java, you can’t sort ints as Strings without an explicit conversion, however, it’s still possible to do it in one operation:

public String largestNumber(int[] num) {
    String s=Arrays.stream(num).mapToObj(Integer::toString)
                   .sorted((n1, n2) -> (n2+n1).compareTo(n1+n2))
                   .collect(Collectors.joining());
    return s.charAt(0) == '0'? "0": s;
}

Upvotes: 1

Bal&#225;zs &#201;des
Bal&#225;zs &#201;des

Reputation: 13816

If String#compareTo is fine for you, then you could really simplify things a bit, and do it with a single Stream chain:

public static String largestNumber(int[] nums) {
    return IntStream.of(nums)
                .mapToObj(Integer::toString)
                .sorted((a, b) -> b.compareTo(a))
                .collect(Collectors.joining());
}

Upvotes: 0

Nir Alfasi
Nir Alfasi

Reputation: 53565

Using Java 8 you can do (almost) the same:

public static void largestNumber(int[] nums) {
    // move int[] to Object[]
    Object[] arr = Arrays.stream(nums)
                            .mapToObj(x -> Integer.toString(x))
                            .toArray();

    //sort by dictionary order
    Arrays.sort(arr);

    // reverse from ascending to descending order
    Collections.reverse(Arrays.asList(arr));

    // back to String and print
    System.out.println(Arrays.stream(arr)
                                .reduce((x, y) -> x.toString() + y.toString())
                                .get());
}

That said, my comment above still stands:

String order (dictionary order) will not help you here, cause it'll return [9, 5, 34, 30, 3] while what you want is: [9, 5, 34, 3, 30]

Upvotes: 0

ZhongYu
ZhongYu

Reputation: 19702

    Arrays.sort(sNum, (a,b)-> (b+a).compareTo(a+b));

    return String.join("", sNum);

Upvotes: 0

serg.nechaev
serg.nechaev

Reputation: 1321

Sort array and not a collection

    public String largestNumber(int[] num) {

      String[] sNum = new String[num.length];

        for(int i = 0;i<num.length; i++){
            sNum[i] = Integer.toString(num[i]);
        }
        Arrays.sort(sNum,(n1, n2) -> (n1 + n2).compareTo(n2 + n1));
        String s = sNum[0];
        for(int i = 1;i<sNum.length;i++)
            s += sNum[i];
        if(s.charAt(0) == '0')
            s = "0";
        return s;
    }

Upvotes: 0

Related Questions