FeelingLikeAJabroni
FeelingLikeAJabroni

Reputation: 255

HashMaps and Lists

I've made a function that reads in a text file and counts the frequency of words by using a hashmap. I've then found the out difficulty of making a function that sorts a hashmap... So after some research, i've found some code that sorts the hashmap by using sets and lists. However, the output of this function is a list, rather than a hashmap. Everything works and does exactly what i want. So my question is, what is the most efficient and effective way to take the contents of the list and put it back into a hashmap, so it can be used with the rest of my code.

EDIT

Okay, so i'm well aware that this can't be achieved as its not the purpose of when using a hashmap. The only reason i asked this is because i had existing code (before i had to implement changes) that outputs it to a file. This worked when using a hashmap, but now it's a list i'm a little stumped.

Cheers

Builds the hashmap

private static HashMap<String, Integer>  theHashMap(String inFileName) throws IOException {

    // Resets collections frequency values to zero
    for (Map.Entry<String, Integer> entry : collection.entrySet()) {
        entry.setValue(0);
    }

    // Reads in the new document file to an ArrayList
    Scanner textFile = new Scanner(new File(inFileName));
    ArrayList<String> file = new ArrayList<String>();

    while(textFile.hasNext()) {
        file.add(textFile.next().trim().toLowerCase());
    }

    for(String word : file) {
        Integer dict = collection.get(word);
        if (!collection.containsKey(word)) {
            collection.put(word, 1); 
        } else {
            collection.put(word, dict + 1);
        }
    }  

    textFile.close();  

    return collection;
}

Sorts the hashmap

private static List<Map.Entry<String, Integer>> sortTheHashMap(HashMap<String, Integer> values) {

    Set<Entry<String, Integer>> set = values.entrySet();
    List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);
    Collections.sort( list, new Comparator<Map.Entry<String, Integer>>()
    {
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2)
        {
            return (o2.getValue()).compareTo(o1.getValue());
        }
    } );
    for(Map.Entry<String, Integer> entry:list){
        System.out.println(entry.getKey()+" = "+entry.getValue());
    }

    return list; 
}

Output to file

    FileWriter fw;
    File fileName;

    fileName = new File("test.txt");
    fw = new FileWriter(fileName, true);

    for (String word : document.getKey()) {
        String key = word.toString();
        String value = document.get(word);
        fw.write(key + " " + value + "\n\n");
    }

    fw.close()

Upvotes: 0

Views: 72

Answers (3)

zpd
zpd

Reputation: 1

JAVA8 Stream

@Test
public void convert_list_to_map_with_java8_lambda () { 

    List<Movie> movies = new ArrayList<Movie>(); 
    movies.add(new Movie(1, "The Shawshank Redemption")); 
    movies.add(new Movie(2, "The Godfather")); 

    Map<Integer, Movie> mappedMovies = movies.stream().collect( 
    Collectors.toMap(Movie::getRank, (p) -> p)); 

    logger.info(mappedMovies); 

    assertTrue(mappedMovies.size() == 2); 
    assertEquals("The Shawshank Redemption", mappedMovies.get(1).getDescription()); 
} 

Upvotes: 0

Malt
Malt

Reputation: 30335

Java HashMaps by definition aren't sorted. It's explicitly written in the 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 a Map sorted by its keys, use a TreeMap:

The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.

However, I'm not sure that a Map is really what you want. A map is used to find a value by a key. A sorted map sorts the keys, and it looks like you want to sort the values (number of occurrences). What if you have two words that appear the same number of times, under what key should they appear?

This is why Collections.sort() return a list - it sorts a given collection and puts the elements in the order you want.

Upvotes: 2

Eran
Eran

Reputation: 394146

If you add the sorted entries to a LinkedHashMap, they will remain sorted (as long as you don't add new keys), since LinkedHashMap maintains insertion order.

Given your List<Map.Entry<String, Integer>>, you can produce the Map as follows:

List<Map.Entry<String, Integer>> entries = ...;
Map<String,Integer> map = entries.stream()
                                 .collect(Collectors.toMap(Map.Entry::getKey,
                                                           Map.Entry::getValue,
                                                           (v1,v2)->v1,
                                                           LinkedHashMap::new));

If your ordering was determined by the keys (instead of by the values), you could have used a TreeMap instead of [Linked]HashMap, which would have taken care of the sorting.

Upvotes: 0

Related Questions