简体   繁体   中英

Converting singly linked list to a map

I have been given an assignment to change to upgrade an existing one.

Figure out how to recode the qualifying exam problem using a Map for each terminal line, on the assumption that the size of the problem is dominated by the number of input lines, not the 500 terminal lines

The program takes in a text file that has number, name. The number is the PC number and the name is the user who logged on. The program returns the user for each pc that logged on the most. Here is the existing code

public class LineUsageData {
    SinglyLinkedList<Usage> singly = new SinglyLinkedList<Usage>();


    //function to add a user to the linked list or to increment count by 1
    public void addObservation(Usage usage){
        for(int i = 0; i < singly.size(); ++i){
            if(usage.getName().equals(singly.get(i).getName())){
                singly.get(i).incrementCount(1);
                return;
            }
        }

        singly.add(usage);
    }
    //returns the user with the most connections to the PC
    public String getMaxUsage(){
        int tempHigh = 0;
        int high = 0;
        String userAndCount = "";
        for(int i = 0; i < singly.size(); ++i){//goes through list and keeps highest
            tempHigh = singly.get(i).getCount();
            if(tempHigh > high){
                high = tempHigh;
                userAndCount = singly.get(i).getName() + " " + singly.get(i).getCount();
            }
        }

        return userAndCount;
    }
}

I am having trouble on the theoretical side. We can use a hashmap or a treemap. I am trying to think through how I would form a map that would hold the list of users for each pc? I can reuse the Usage object which will hold the name and the count of the user. I am not supposed to alter that object though

When checking if Usage is present in the list you perform a linear search each time ( O(N) ). If you replace your list with the Map<String,Usage> , you'll be able to search for name in sublinear time. TreeMap has O(log N) time for search and update, HashMap has amortized O(1) (constant) time.

So, the most effective data structure in this case is HashMap .

import java.util.*;

public class LineUsageData {
    Map<String, Usage> map = new HashMap<String, Usage>();

    //function to add a user to the map or to increment count by 1
    public void addObservation(Usage usage) {
        Usage existentUsage = map.get(usage.getName());
        if (existentUsage == null) {
            map.put(usage.getName(), usage);
        } else {
            existentUsage.incrementCount(1);
        }
    }

    //returns the user with the most connections to the PC
    public String getMaxUsage() {
        Usage maxUsage = null;
        for (Usage usage : map.values()) {
            if (maxUsage == null || usage.getCount() > maxUsage.getCount()) {
                maxUsage = usage;
            }
        }

        return maxUsage == null ? null : maxUsage.getName() + " " + maxUsage.getCount();
    }

    // alternative version that uses Collections.max
    public String getMaxUsageAlt() {
        Usage maxUsage = map.isEmpty() ? null :
                Collections.max(map.values(), new Comparator<Usage>() {
                    @Override
                    public int compare(Usage o1, Usage o2) {
                        return o1.getCount() - o2.getCount();
                    }
                });

        return maxUsage == null ? null : maxUsage.getName() + " " + maxUsage.getCount();
    }

}

Map can also be iterated in the time proportional to it's size, so you can use the same procedure to find maximum element in it. I gave you two options, either manual approach, or usage of Collections.max utility method.

With simple words: You use a LinkedList (singly or doubly) when you have a list of items, and you usually plan to traverse them, and a Map implementation when you have "Dictionary-like" entries, where a key corresponds to a value and you plan to access the value using the key.

In order to convert your SinglyLinkedList to a HashMap or TreeMap , you need find out which property of your item will be used as your key (it must be an element with unique values).

Assuming you are using the name property from your Usage class, you can do this (a simple example):

//You could also use TreeMap, depending on your needs.
Map<String, Usage> usageMap = new HashMap<String, Usage>();

//Iterate through your SinglyLinkedList.
for(Usage usage : singly) {
    //Add all items to the Map
    usageMap.put(usage.getName(), usage);
}

//Access a value using its name as the key of the Map.
Usage accessedUsage = usageMap.get("AUsageName");

Also note that:

Map<string, Usage> usageMap = new HashMap<>();

Is valid, due to diamond inference .

I Solved this offline and didn't get a chance to see some of the answers which looked to be both very helpful. Sorry about that Nick and Aivean and thanks for the responses. Here is the code i ended up writing to get this to work.

public class LineUsageData {

    Map<Integer, Usage> map = new HashMap<Integer, Usage>();
    int hash = 0;
    public void addObservation(Usage usage){
        hash = usage.getName().hashCode();
        System.out.println(hash);
        while((map.get(hash)) != null){
            if(map.get(hash).getName().equals(usage.name)){
                map.get(hash).count++;
                return;
            }else{
                hash++;
            }

        }
        map.put(hash, usage);
    }






    public String getMaxUsage(){
        String str = "";
        int tempHigh = 0;
        int high = 0;

    //for loop
        for(Integer key : map.keySet()){
            tempHigh = map.get(key).getCount();
            if(tempHigh > high){
                high = tempHigh;
                str = map.get(key).getName() + " " + map.get(key).getCount();
            }
        }

        return str;
    }


}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM