2

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.
  }
1
  • The above solution is returning {Hello World=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}. The first for loop could simply be replaced by char[] sArray =s.toCharArray(); Commented Jul 20, 2020 at 2:30

4 Answers 4

3

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

Sign up to request clarification or add additional context in comments.

2 Comments

thanks! but looking back at my instructions, it looks that what I need to do is accept a string and return the string's characters mapped out with their indexes. gonna update my question
I modified the above so it works with String. It converts the char ch to a String by appending an empty String to it.
2

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);

3 Comments

How does that help the OP solve their current algorithm?
@WJS It provides an alternative solution, I suppose.
This works! I realized after posting that I was misunderstanding the requirement -- that I need to make it map a string as a key, not also the bit about characters.
0

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.

2 Comments

"The code is self explanatory." - I'm not too sure about that.
@hev1 Thanks for your comment, the code has been updated with the respective comments.
0
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());
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.