I am currently throwing an obfuscation program for school homework together. I am trying to make the program read a file and then create a new file that replaces each letter in the file with some a corresponding value that I pull from a HashMap
. I set up a whole bunch of keys and values, but later in the process of writing the new file I try to check if the map contains a key before appending to the new String
. The characters that are checked are in fact in the file that I am reading from to test, and the file is read correctly. Yet it fails with the encryptionDict.containsKey()
(my hashmap) method.
I hope some Java expert can help me figure this out! I'm pretty clueless, I'm more of a C and D guy. The only thought that struck me was that it would be something like with Strings where "foo" != "foo"
. But chars aren't objects.
The code is in a pastebin below, the key parts to look at is the class constructor, the method encrypt, and the method initDictionary
, also can someone tell me why HashMap<char, String>
is invalid, is it because I have to use an object?
The code: http://pastebin.com/NcHTHPfw
private HashMap<char [], String> initDictionary() {
HashMap<char [], String> d = new HashMap<char [], String>();
d.put("a".toCharArray(), "!\"#¤");
d.put("b".toCharArray(), "¤#\"!");
d.put("c".toCharArray(), "\"#¤%");
d.put("d".toCharArray(), "%¤#\"");
d.put("e".toCharArray(), "#¤%&");
d.put("f".toCharArray(), "&%¤#");
d.put("g".toCharArray(), "¤%&/");
d.put("h".toCharArray(), "/&%¤");
d.put("i".toCharArray(), "%&/(");
d.put("j".toCharArray(), "(/&%");
d.put("k".toCharArray(), "&/()");
d.put("l".toCharArray(), ")(/&");
d.put("m".toCharArray(), "/()=");
d.put("n".toCharArray(), "=)(/");
d.put("o".toCharArray(), "()=?");
d.put("p".toCharArray(), "?=)(");
d.put("q".toCharArray(), ")=?!");
d.put("r".toCharArray(), "!?=)");
d.put("s".toCharArray(), "=?!\"");
d.put("t".toCharArray(), "\"!?=");
d.put("u".toCharArray(), "?!\"#");
d.put("v".toCharArray(), "#\"!?");
d.put("w".toCharArray(), ";:*^");
d.put("x".toCharArray(), "^*:;");
d.put("y".toCharArray(), ":*^>");
d.put("z".toCharArray(), ">^*:");
// etc.
This is the problematic bit. You can't use arrays as hash keys in Java, as Array does not override the equals() and hashCode() methods.
The hashCode is used to find the correct bucket that contains the object you are looking for, and the equals() method compares the actual Objects. To make use of a HashMap, you need to override both of these methods in a sensible way, which you can't as array classes are final. So the only thing you could do if you absolutely insist on using char arrays is to use a wrapper class as key that has a char array.
Something like this:
public class Key {
private final char[] array;
public Key(final String string) {
this(string.toCharArray());
}
public Key(final char[] array) {
this.array = array;
}
public char[] getArray() {
return array;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (!Arrays.equals(array, key.array)) return false;
return true;
}
@Override
public int hashCode() {
return array != null ? Arrays.hashCode(array) : 0;
}
}
Now you can have a Map<Key, String>
and bould a Key
Object from either a String
or a char[]
The problem is that all char[]
are unique, regardless of their contents. It appears you really want to be using a String. Normally, you can write such a program without using a char[]
Instead you can write
private Map<Character, String> initDictionary() {
Map<Character, String> d = new HashMap<Character, String>();
d.put('a', "!\"#¤");
// etc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With