I've tried two ways, A is sorting the characters of both strings alphabetically and comparing the results, B is counting every character in both strings and comparing the counts. I'd prefer A over B regarding readability.
public boolean isAnagramA(String a, String b) {
if (a.length() != b.length()) {
return false;
}
char[] aAsArray = a.toUpperCase().toCharArray();
char[] bAsArray = b.toUpperCase().toCharArray();
Arrays.sort(aAsArray);
Arrays.sort(bAsArray);
return Arrays.equals(aAsArray, bAsArray);
}
public int numberOf(char needle, char[] haystack) {
int count = 0;
for (int i = 0; i < haystack.length; i++) {
if (haystack[i] == needle) {
count++;
}
}
return count;
}
public boolean isAnagramB(String a, String b) {
if (a.length() != b.length()) {
return false;
}
char[] aAsArray = a.toUpperCase().toCharArray();
char[] bAsArray = b.toUpperCase().toCharArray();
for (int i = 0; i < aAsArray.length; i++) {
if (numberOf(aAsArray[i], aAsArray) != numberOf(aAsArray[i], bAsArray)) {
return false;
}
}
return true;
}
public void run() {
{
long start = System.nanoTime();
System.out.println(isAnagramA("OTTO", "TOT"));
System.out.println(isAnagramA("OTTO", "TOTO"));
System.out.println(isAnagramA("LOTTO", "TOLLO"));
System.out.println(isAnagramA("yarm", "army"));
System.out.println(isAnagramA("Yarm", "Army"));
System.out.println(isAnagramA("SMAISMRMILMEPOETALEVMIBVNENVGTTAVIRAS",
"AltissimvmPlanetamTergeminvmObservavi"));
System.out.println((System.nanoTime() - start) + " ns for 6 x A");
}
{
long start = System.nanoTime();
System.out.println(isAnagramB("OTTO", "TOT"));
System.out.println(isAnagramB("OTTO", "TOTO"));
System.out.println(isAnagramB("LOTTO", "TOLLO"));
System.out.println(isAnagramB("yarm", "army"));
System.out.println(isAnagramB("Yarm", "Army"));
System.out.println(isAnagramB("SMAISMRMILMEPOETALEVMIBVNENVGTTAVIRAS",
"AltissimvmPlanetamTergeminvmObservavi"));
System.out.println((System.nanoTime() - start) + " ns for 6 x B");
}
{
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
isAnagramA("SMAISMRMILMEPOETALEVMIBVNENVGTTAVIRAS", "AltissimvmPlanetamTergeminvmObservavi");
}
System.out.println((System.currentTimeMillis() - start) + " ms for 1000000 x A");
}
{
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
isAnagramB("SMAISMRMILMEPOETALEVMIBVNENVGTTAVIRAS", "AltissimvmPlanetamTergeminvmObservavi");
}
System.out.println((System.currentTimeMillis() - start) + " ms for 1000000 x B");
}
}
Method run() is used to test whether it works (not JUnit, just output) and which ways is faster, this is the output:
false
true
false
true
true
true
579384 ns for 6 x A
false
true
false
true
true
true
252453 ns for 6 x B
1310 ms for 1000000 x A
1333 ms for 1000000 x B
At first A seems to be two times slower but looping 1000000 times over checking Galileo Galilei's anagram shows almost no difference in performance (hopefully it's not due to compiler optimization).
I do agree with other commenters about caring for correctness and readability first and research optimizations only if and where there is a real need for it.