Creating a HashMap of chars in a string and integers in an ArrayList<integer>

Viewed 2505

I have to create a HashMap that records the letters in a string and their index values in a ArrayList, so that if the HashMap is called with some string key, each related index integer is returned, and so that the map can be called by itself such that each key is shown with their indexes, For example for the string "Hello World", the map would look something like:

d=[9], o=[4, 6], r=[7], W=[5], H=[0], l=[2, 3, 8], e=[1].

I'm really confused by the requirement of the inputs as String and ArrayList, rather than chars and integers. Could you explain to me the relationship of the map to those objects, and to their components which are ultimately what are recorded as keys and values? When trying to debug, it stops processing before the map call.

The error message is:

java.lang.AssertionError: Wrong number of entries in Concordance. Expected: 5. Got: 1 
Expected :1
Actual   :5

But I really think I'm not grasping HashMap very well, so I'd appreciate if anyone could guide me through the basics, or provide anything educational about using HashMap, especially ones that use ArrayList.

public HashMap<String, ArrayList<Integer>> concordanceForString(String s) {
    HashMap<String, ArrayList<Integer>> sMap = new HashMap<>();//create map "sMap"
    char[] sArray = new char[s.length()]; //create character array, "sArray", for string conversion
    ArrayList<Integer> sCharIndex =  new ArrayList<Integer>();
    for (int i = 0; i < s.length(); i++) {
      sArray[i] = s.charAt(i); // convert string into array
    }
    for (int j = 0; j < sArray.length; j++){
      sCharIndex.add(j); // add char indexes to index ArrayList
    }
    sMap.put(s, sCharIndex); //add the String and ArrayList 
    return sMap; // I feel like this should be sMap.get(s) but when I do, it gives me the zigzag red underline.
  }
4 Answers

Essentially, this is what you want to do.

This presumes a HashMap<String, List<Integer>>

List<Integer> sCharIndex;
for (int i = 0; i < s.length(); i++) {
    // get the character
    char ch = s.charAt(i);
    if (!Character.isLetter(ch)) {
       // only check letters 
       continue;
    }
    ch = ch+""; // to string       
    // get the list for character
    sCharIndex = sMap.get(ch);
    // if it is null, create one and add it
    if (sCharIndex == null) {
      // create list
      sCharIndex = new ArrayList<>();
      // put list in map
      sMap.put(ch, sCharIndex);
    }
    // at this point you have the list so
    // add the index to it.
    sCharIndex.add(i);
}
return sMap;

A hashMap is nothing more than a special data structure that takes an object as a key. Think of an array that takes a digit as an index and you can store anything there.

A hashMap can take anything as a key (like an index but it is called a key) and it can also store anything.

Note that your key to hashMap is a String but you're using a character which is not the same. So you need to decide which you want.

HashMap<String, List<Integer>> or HashMap<Character, List<Integer>>

There are also easier ways to do this but this is how most would accomplish this prior to Java 8.

Here is a much more compact way using streams. No loops required.

Map<String, List<Integer>> map2 = IntStream
        .range(0,s.length())
         // only look for letters.
        .filter(i->Character.isLetter(s.charAt(i)))
        .boxed()
         // stream the Integers from 0 to length
         // and group them by character in a list of indices.
        .collect(Collectors.groupingBy(i->s.charAt(i)+""));

But I recommend you become familiar with the basics before delving into streams (or until your instructor recommends to do so). For more information check out The Java Tutorials

Here is a way to do it:

String input = "hello world";
Map<String, List<Integer>> letters = new HashMap<String, List<Integer>>();

// remove all whitespace characters - since it appears you are doing that 
String string = input.replaceAll("\\s", "");

// loop over the length of the string
for (int i = 0; i < string.length(); i++) {
    // add the entry to the map
    // if it does not exist, then a new List with value of i is added
    // if the key does exist, then the new List of i is added to the 
    // existing List
    letters.merge(string.substring(i, i + 1), 
        Arrays.asList(i), 
        (o, n) -> Stream.concat(o.stream(), n.stream()).collect(Collectors.toList()));
}
            
System.out.println(letters);

that gives this output:

{r=[7], d=[9], e=[1], w=[5], h=[0], l=[2, 3, 8], o=[4, 6]}

EDIT - this uses a Character as the key to the map:

String input = "hello world";
Map<Character, List<Integer>> letters = new HashMap<Character, List<Integer>>();

String string = input.replaceAll("\\s", "");
for (int i = 0; i < string.length(); i++) {
    letters.merge(string.charAt(i), Arrays.asList(i), (o, n) -> 
        Stream.concat(o.stream(), n.stream()).collect(Collectors.toList()));
}
            
System.out.println(letters);

Check out this code :

 public static void main(String []args){
    //Create map of respective keys and values
    HashMap<Character, ArrayList<Integer>> map = new HashMap(); 
    String str = "Hello world"; //test string
    int length = str.length(); //length of string
    for(int i = 0; i < length; i++){ 
        ArrayList<Integer> indexes = new ArrayList(); //empty list of indexes
        //character of test string at particular position 
        Character ch = str.charAt(i);  
        //if key is already present in the map, then add the previous index associated with the character to the indexes list
        if(map.containsKey(ch)){ 
            //adding previous indexes to the list
            indexes.addAll(map.get(ch));
        }
        //add the current index of the character to the respective key in map
        indexes.add(i); 
        //put the indexes in the map and map it to the current character
        map.put(ch, indexes);
    }
    //print the indexes of 'l' character
    System.out.print(map.get('l')); 
 }

The code is self explanatory.

public class Array {

public static void main(String[] args) {

    printSortedMap(concordanceForString("Hello world"));   // r[7] d[9] e[1] w[5]  H[0] l[2, 3, 8] o[4, 6]
    
}


public static HashMap<String, ArrayList<Integer>> concordanceForString(String s) {
    HashMap<String, ArrayList<Integer>> sMap = new HashMap<>();
    String str = s.replace(" ", "");

    for (int i = 0; i < str.length(); i++) {
        ArrayList<Integer> sCharIndex =  new ArrayList<Integer>();

        for (int j = 0; j < str.length(); j++) {
            if ( str.charAt(i) == str.charAt(j) ) {
                sCharIndex.add(j);
            }
        }
        sMap.put(str.substring(i,i+1), sCharIndex);
    }
    return sMap;
}


public static void printSortedMap(HashMap<String, ArrayList<Integer>> sMap) {
    for (Map.Entry<String, ArrayList<Integer>> entry : sMap.entrySet()) {
        System.out.println(entry.getKey() + entry.getValue());
    }
}
Related