String.charAt() returning weird result in java

Viewed 1099

i have the following code

String[] alphabet = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
                "o", "p", "q","r", "s", "t", "u", "v", "w", "x", "y", "z"};

if i do

 String str = "aa";
 for(int i=0;i<str.length();i++) {
    chars.add(Arrays.asList(alphabet).indexOf(str.charAt(i)));
 }

the values in chars are

0 = -1
1 = -1 

as the result returned by Arrays.asList(alphabet).indexOf(str.charAt(i)) is 'a'97 and not "a" hence its not matching due to which -1 is being returned

I need Arrays.asList(alphabet).indexOf(str.charAt(i)) to return "a" that's what i thought charAt returns which is just "a" and not this 'a' 97

any alternative ?

6 Answers

str.charAt(i) returns a char and the List contains String elements.
As a char is not a String and String.equals() and Character.equals() are not interoperable between them ("a".equals('a') and Character.valueOf('a').equals("a") return false), stringList.indexOf(anyChar) will always return -1.

You could replace :

chars.add(Arrays.asList(alphabet).indexOf(str.charAt(i)));
                ^----- List<String>          ^----- char (that will be boxed to Character)

by :

chars.add(Arrays.asList(alphabet).indexOf(String.valueOf(str.charAt(i))));
                ^----- List<String>             ^----- String

to compare String with String.

Or as alternative compare char with char by relying on char[] instead of String[] such as :

char[] alphabet = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q','r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; 

In this way this will compile fine :

List<Character> charList = IntStream.range(0, alphabet.length)
                                          .mapToObj(i -> alphabet[i])
                                          .collect(Collectors.toList());
chars.add(charList.indexOf(str.charAt(i))); 
            ^------- List<Character>      ^------ char (that will be boxed to Character)

Not your direct question but creating the same List at each iteration is not logical and is a little some waste.
Instantiating it once before the loop is more efficient :

List<String> alphabetList = Arrays.asList(alphabet);
String str = "aa";
for(int i=0;i<str.length();i++) {
   chars.add(alphabetList.indexOf(String.valueOf(str.charAt(i))));
}

It's important to note that chars and Strings are not the same thing in Java. A char is a primitive, numerical type, and its literals are given using single quotes (e.g. 'a'). A String is a reference type that logically consists of multiple characters.

The simplest solution would be to make your alphabet a single string:

String alphabet = "abcdef...";

and to scan that string when finding the index:

 chars.add(alphabet.indexOf(str.charAt(i)));

Note that this now uses String.indexOf and not the List indexOf method that you were using before.

Alternatively, convert alphabet to be an array of characters:

char[] alphabet = new char[] {'a', 'b', /* ... */ };

Arrays.asList(alphabet) is a List<String>. It does not contain anything of type Character.

If you want to look for a String consisting of that single character, build a string of that single character:

Arrays.asList(alphabet).indexOf(Character.toString(str.charAt(i)))

or

Arrays.asList(alphabet).indexOf(str.substring(i, i+1))

This is because char != string in java,

So to resolve your problem,

Arrays.<String>asList(alphabet).indexOf(Character.toString(str.charAt(i)))

Now you will get your output as expected.

So the problem was that you created List of String and was looking for a character in string so java was unable to find it. So it returned -1.

You could convert the String to a character array and iterate through that:

    List<Integer> indices = new ArrayList<>();

    String str = "abc";

    for ( Character character : str.toCharArray() )
    {
        indices.add(Arrays.asList(alphabet).indexOf(character.toString()));
    }

It is possible to do integer operations on char - it is an integral type (displayed as character). Examples: 'b' - 'a' == 1, 'c' - 'a' == 2, and so on. (Actually 'a' == 97 , its Unicode value).

For the given code, there is no need for the array or a list, it could be written as

for (int i=0; i<str.length(); i++) {
    chars.add(str.charAt(i) - 'a');
}

sure the loop can be written as

for (char ch : str.toCharArray()) {
    chars.add(ch - 'a');
}

or even using streams:

str.chars().map(ch -> ch - 'a').forEach(chars::add)

missing the type of chars, I just assumed it is List<Integer>

Related