0
String s5 = "peek";
int i[] = {12, 25, 7, 3, 45};
Arrays.sort(i);

for(int x : i) {
  System.out.print(x + ",");
}

Arrays.sort(s5.toCharArray());

System.out.println(s5); // expected here eekp, but showing peek

for(char c : s5.toCharArray()) {
  System.out.print(c + ",");  //expected here e,e,k,p , but showing p,e,e,k
}

Output:

3,7,12,25,45,peek
p,e,e,k,

for the line System.out.println(s5) I expected "eekp" but it's showing "peek".

for the line System.out.print(c + ",") I expected "e,e,k,p" but it's showing "p,e,e,k"

Arrays sort seems to work well for integers but not for character array, seems like am doing something wrong. could you please tell me?

4
  • 9
    Every time you call toCharArray you get a new char array with a copy of the string's content. You can't actually alter the content of the string. Strings are immutable. Commented Feb 11, 2021 at 0:45
  • 3
    hi, after sorting the char array, perhaps create a new string with the sorted value. char[] chars = s5.toCharArray(); Arrays.sort(chars); String newString = new String(chars); Commented Feb 11, 2021 at 0:45
  • 3
    Hint: What does s5.ToCharArray() return? Commented Feb 11, 2021 at 0:46
  • 4
    Specifically: read through the docs for String.toCharArray: what does it do? How does that differ from what you assumed? Commented Feb 11, 2021 at 0:48

4 Answers 4

4

Strings are immutable (mostly)

Arrays.sort(s5.toCharArray());

The above sorts a copy of the character array and does not modify the actual string value array.

The internal code of toCharArray in JDK 1.8

  char result[] = new char[value.length];
  System.arraycopy(value, 0, result, 0, value.length);

Store and sort the copy(new object in a reference)

char[] copy = s5.toCharArray();
Arrays.sort(copy);

Do not try unless for fun

  Field field = String.class.getDeclaredField("value");
  field.setAccessible(true);
  String s5 = "peek";
  Arrays.sort((char[]) field.get(s5));
  System.out.println(s5);
Sign up to request clarification or add additional context in comments.

5 Comments

What do you mean by "Strings are immutable (mostly)" ? Is there something that I am missing? Because I would like to know.
@AniketSahrawat, If we use reflection, then we can modify a String. the last section of the answer(Do not try section) will modify the original String object. If we have another reference variable pointing to the same string, then the change is visible to other reference variable also. I have added the complete code here: stackoverflow.com/questions/66090999/…
The behavior of reflection is slowly changing in Java. With Java 16, code using reflection to access internal JDK apis will result in error by default. I think, its controlled by --illegal-access=deny flag. Many frameworks rely on reflection to simplify the user experience(like test frameworks, Dependency injection), so still it might be needed. Basically at current level, reflection can break most of the encapsulation logic.
It won't behave the same as java 8 even if illegal access is permitted.
True, with the addition of modules there has been a good amount of change. (and this has caused a great deal change in the mock frameworks used in unit tests). I haven't worked much on these latest changes though. Thank you for the good discussion.
3

The Answer by Horse is correct. Your code is discarding a newly created array immediately after sorting. You passed a new anonymous array to Arrays.sort, which sorted that new array, and then the new array went out-of-scope, as you neglected to put the array into a variable.

In addition, I can show code using Unicode code points rather than char.

Unicode code point numbers

The char type in Java is obsolete, unable to represent even half of the characters defined in Unicode. Instead, you should be working with the code point numbers, one number assigned to each character in the Unicode standard.

You can get a stream (IntStream) of those integer code point numbers by calling String#codePoints.

Here is some example code. As an input we use a string that contains a couple of emoji characters. Using char type, we incorrectly see four ? where we expect two character numbers. Then we use code points, and we correctly see a pair of numbers (128075, 128506) for the pair of emoji characters. Lastly, we use Java streams to sort the code point numbers, and collect the sorted numbers to build a new String object.

String input = "👋🗺 Hello World.";
System.out.println( "input = " + input );

// Wrong way, using obsolete `char` type.
char[] chars = input.toCharArray();
System.out.println( "chars before sort: " + Arrays.toString( chars ) );  // Notice that we get *four* `?` where we expect *two* letters (each of two emoji).
Arrays.sort( chars );
System.out.println( "chars after sort: " + Arrays.toString( chars ) );

// Examining code points.
System.out.println( "Print the code point number for each letter in the string. Notice we get *two* larger numbers, one for each emoji." );
input.codePoints().forEach( System.out :: println );

// Sorting by code point numbers.
String sorted =
        input
                .codePoints()
                .sorted()
                .collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
                .toString();
System.out.println( "sorted = " + sorted );

When run.

input = 👋🗺 Hello World.
chars before sort: [?, ?, ?, ?,  , H, e, l, l, o,  , W, o, r, l, d, .]
chars after sort: [ ,  , ., H, W, d, e, l, l, l, o, o, r, ?, ?, ?, ?]
Print the code point number for each letter in the string. Notice we get *two* larger numbers, one for each emoji.
128075
128506
32
72
101
108
108
111
32
87
111
114
108
100
46
sorted =   .HWdellloor👋🗺

The first two characters in sorted are actually SPACE characters, originally found between the words in input.

Instead of the streams, we could use arrays.

int[] codePoints = input.codePoints().toArray();
System.out.println( "codePoints before sorting = " + Arrays.toString( codePoints ) );
Arrays.sort( codePoints );
System.out.println( "codePoints after sorting = " + Arrays.toString( codePoints ) );

When run. Notice how the 32 number twice represents the two SPACE characters.

codePoints before sorting = [128075, 128506, 32, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 46]
codePoints after sorting = [32, 32, 46, 72, 87, 100, 101, 108, 108, 108, 111, 111, 114, 128075, 128506]

For more info, read The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).

1 Comment

This is the complete answer in the context of internalization. Java's contract to char as a 16-bit unsigned type has limited the evolution of the current String methods ability to transparently handle unicode characters(codepoints). There are methods in String that can help us achieve the desired length and substring methods. It requires a slight perspective change. May be Java should introduce a UnicodeString class to completely overhaul this behavior.
3

Change Arrays.sort(s5.toCharArray()); To char[] s6 = s5.toCharArray()): Arrays.sort(s6);

Then print the values of s6

toCharArray() gives you a new array from the source but doesn't modify the source. When you print you are printing the source array not the array containing the sorted char

4 Comments

And, importantly, Java Strings are immutable. There is no other way to reorder the characters of one, either.
What result do you expect from s6.toCharArray()?
I think it should be: char[] s6 = s5.toCharArray()): Arrays.sort(s6);
@john thanks for pointing out. Modified the code in answer
-1

A bit late to the party, but with the java stream api's you could also solve it like this:

public static String sort(String value) {
    return value.chars()
            .sorted()
            .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
            .toString();
}

or with a custom comparator (if your strings contain only Basic Multilingual Plane characters):

public String sort(String value, Comparator<Character> comparator) {
    return value.chars()
        .mapToObj(ch -> (char) ch)
        .sorted(comparator)
        .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
        .toString();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.