Weiheng Li
Weiheng Li

Reputation: 57

Using comparator for char array, but get no suitable method found

I am trying to use the value of freq to sort all the a-z chars. However it is not working. Could someone explain why the following code is not working please? And how can I sort the array as I want? Thank you.

        char[] chars = new char[26];
        int[] freq = new int[26];
        for(int i = 0;i<26;i++){
            chars[i] = (char)(i+'a');
        }
        for(char c:s.toCharArray()){
            freq[c-'a']++;
            if(freq[c-'a']>(s.length()+1)/2){
                return "";
            }
        }
        Arrays.sort(chars, (a, b)->(freq[b-'a'] - freq[a-'a']));

error: no suitable method found for sort(char[],(a,b)->(fr[...]'a'])) Arrays.sort(chars, (a, b)->(freq[b-'a'] - freq[a-'a'])); ^ method Arrays.<T#1>sort(T#1[],Comparator<? super T#1>) is not applicable (inference variable T#1 has incompatible bounds equality constraints: char lower bounds: Object) method Arrays.<T#2>sort(T#2[],int,int,Comparator<? super T#2>) is not applicable (cannot infer type-variable(s) T#2 (actual and formal argument lists differ in length)) where T#1,T#2 are type-variables: T#1 extends Object declared in method <T#1>sort(T#1[],Comparator<? super T#1>) T#2 extends Object declared in method <T#2>sort(T#2[],int,int,Comparator<? super T#2>)

Upvotes: 0

Views: 338

Answers (2)

Supritam
Supritam

Reputation: 289

According to the javadocs, Arrays.sort with a comparator is only applicable on Objects not primitives.

Arrays.sort(char[]) sorts on numerical order.

Just to solve your problem:

    String s = "hello";
    Map<Character, Integer> returnMap = new HashMap<Character, Integer>();
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    for (int i = 0; i < 26; i++) {
        map.put (Character.valueOf((char)(i + 'a')), 0);
    }

    for (char c : s.toCharArray()) {
        Integer freq = map.get(Character.valueOf(c));
        map.put(Character.valueOf(c),++freq);
    }
    List<Map.Entry<Character,Integer>> listToSort = new LinkedList<>(map.entrySet());
    Collections.sort(listToSort, (m1, m2)->(
        m2.getValue().compareTo(m1.getValue())
            )
    );
    listToSort.forEach(entry -> System.out.println(entry.getKey()+":"+entry.getValue()));

Upvotes: 2

Basil Bourque
Basil Bourque

Reputation: 338326

The Answer by Supritam is correct. I’ll add a workaround.

The char type is legacy, essentially broken. As a 16-bit value, char is physically incapable of representing most characters.

Instead use code point integer numbers to work with individual characters.

Map of code point to count

Rather than use a pair of arrays, use a Map, a collection of key-value pairings.

Map< Integer , Integer > map = new HashMap<>();
someString
        .codePoints()
        .forEach( 
            codePoint -> map.put( codePoint , map.containsKey( codePoint ) ? map.get( codePoint ) + 1 : 1 ) 
        ) ;

We now have a count of occurrences of each code point. But the goal in the Question is to report results sorted by the count of occurrences.

That count is the value on our map. So we need to sort the map by value. There are several ways to do that, as discussed in this article.

List< Entry< Integer , Integer > > list = new ArrayList<>( map.entrySet() );
list.sort( 
    Entry.comparingByValue().thenComparing( Entry.comparingByKey() ) ;
);
list.forEach( ( Entry< Integer , Integer > entry ) -> System.out.println( entry.getValue() + " occurrences of " + Character.toString( entry.getKey() ) ) );

All that code is untested. Hopefully it is close enough to working to guide you.

Upvotes: 2

Related Questions