2
HashMap<Character,Character> h=new HashMap<>();
for(int i=0; i<str.length(); i++){
    h.put(str.charAt(i),str.charAt(i));
}
Set<Character> keys=h.keySet();

Character [] arr=new Character[keys.size()];

keys.toArray(arr);
String ans="";
for(int i=0; i<arr.length; i++) {
    ans+=arr[i];
}

In this question I have to remove duplicates from the string entered.It works fine for normal characters but when input is like: o&6nQ0DT$3 i.e. containing special characters then it does not get printed in order.

input: o&6nQ0DT$3
expected output: o&6nQ0DT$3 
my output: 0Q3DT$&6no

I am getting the value returned by keyset() method in a set "keys" (because return type is set internally of keyset()) after that I created an array of length keys and put the string into it for returning. But its coming in different order.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • HashMap does not have a fixed order. (From the HashMap javaDoc: "This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.") If you want your Map to keep the order of insertion use LinkedHashMap instead – OH GOD SPIDERS Apr 26 '17 at 16:48
  • 1
    (1) Don't use Map since you don't need mapping, but guarantee for uniqueness of elements which is role of Set. (2) HashMap (or HashSet) doesn't preserve insertion order (or any particular order). To preserve it use LinkedHashMap, or in your case LinkedHashSet. – Pshemo Apr 26 '17 at 16:48

5 Answers5

3

A HashMap (or HashSet, for that matter) has no intrinsic order. The fact that this worked for some inputs is just a lucky stroke. You could use a LinkedHashMap, as @javaguy suggests, or it may be easier to implement this entire exercise using streams:

String input =  "o&6nQ0DT$3";
String output = input.chars()
                     .distinct()
                     .mapToObj(c -> String.valueOf((char) c))
                     .collect(Collectors.joining());
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

HashMap does not guarantee/retain the insertion order of the elements, so use LinkedHashMap to preserve the order of the characters you are inserting:

Map<Character,Character> h = new LinkedHashMap<>();//use LinkedHashMap
Vasu
  • 21,832
  • 11
  • 51
  • 67
1

can it be done without HashMap?

    String str = "Teste";
    String finalStr = ""; 

    for (Character charInString: str.toCharArray()) {
        if(!finalStr.contains(charInString.toString()))
        {
            finalStr += charInString;
        }

    }
    System.out.println(finalStr);

Improving, what about it? A Workaround with TreeSet.

    String str = "teste";
    HashMap<Integer, Character> map = new HashMap<>();
    for (int i = 0; i < str.length(); i++) {
        if (!map.containsValue(str.charAt(i))) {
            map.put(i, str.charAt(i));
        }
    }
    SortedSet<Integer> keys = new TreeSet<Integer>(map.keySet());
    keys.forEach(k -> System.out.println(k + " value " + map.get(k).toString()));
1

LinkedHashMap & LinkedHashSet maintains the insertion order.

String s = "o&6nQ0DT$3";
Map<Character,Character> hm = new LinkedHashMap<>();    
for(Character c:s.toCharArray())
    hm.put(c, c);
System.out.println(hm);

Output :

{o=o, &=&, 6=6, n=n, Q=Q, 0=0, D=D, T=T, $=$, 3=3}

But LinkedHashSet internally uses hashmap to store the values, so the performance will be slightly better in LinkedHashMap.

vijayraj34
  • 2,135
  • 26
  • 27
0

I don't see how are you fully using a hashmap, perhaps you would like to replace with a ArrayList, like this:

ArrayList<Character> h = new ArrayList<>();
for(int i=0;i<str.length();i++)
{
   if(!h.contains(str.charAt(i)))
      h.add(str.charAt(i));
   }
...

An arraylist will keep the same order of insertion too.