Java HashMap multiple keys with multiple values assigned flexible - java

I have a problem with my Java Code. I want to store multiple Values in one Key but I want to store them flexible. This means I read from a textfile and every line is one word. To store them, I want to build pairs of words. For example:
word1/word2
word2/word3
word3/word4
I have changed this method a little bit. I want to store the values of the keys in an arraylist. This means everytime when a new key comes up a new Arraylist and key will be stored, but if the key is in the map I want to store them in the list of this key. Is this possible?
We have to store them in a hashmap. But I can not get it to work:
private HashMap<String, ArrayList<String>> hmap = new HashMap<String, ArrayList<String>>();
private ArrayList<String> wort2;
public GrammelotH(String filename) throws IOException {
String fixWort = ".";
BufferedReader br = new BufferedReader(new FileReader(filename));
while (br.ready()) {
String line = br.readLine();
if (hmap.containsKey(fixWort)) {
hmap.put(fixWort, wort2.add(line));
}else {
hmap.put(fixWort, new ArrayList<String>().add(line));
}
fixWort = line;
}
br.close();
}
The problem is the put order. Has anybody of you an idea how to get
hmap.put(fixWort, new ArrayList<String>().add(line));
and
hmap.put(fixWort, wort2.add(line));
to work?
Thank you for your help!
Bye Bye!

I think I'd be looking at something like
List l = hmap.get(line);
if (l != null) {
l.add(line));
}else {
l = new ArrayList<String>();
l.add(line)
hmap.put(line, l);
}
So, you see if the map already contains the line you have just read from the file. If it does, you just add it to the associated list. If it doesn's.create a list, add line to it, and then add both to the Map.

Related

Inserting values in LinkedHashMap without using the key

I have a table data in CSV format. First row contains all column names(keys) and all subsequent rows are records(values) as shown below:
ID,Name,Contact,Address
1,Alex,987654321,CA USA
2,Bob,4489398,LA USA
3,Marley,7236487,Washington
I am reading this file and trying to store the records as key value pair in LinkedHashMap. Here is my code to show what I am trying to do. My question is written in the code as comment.
public static void readCSV() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("table.csv"));
Map<String, ArrayList<String>> map = new LinkedHashMap<>();
String line = br.readLine();
String[] keys = line.split(",");
/*insert all keys with a corresponding empty arraylist as value to store
all values of a particular key. ie each arralist will contain all values
of individual columns. Since it is a linkedhashmap, keys are stored in
same order as they appear in the csv file*/
for (String key : keys) {
map.put(key, new ArrayList<String>());
}
while((line = br.readLine())!=null){
String[] values = line.split(",");
for (String value : values) {
/*here I want to get the arraylists sequentially to store value.
I know the first value goes in the first arraylist, second goes
to second arraylist and so on.
Is there a way to do this without using the key here??
*/
}
}
}
You can use an Iterator to iterate over the values of your Map :
while((line = br.readLine())!=null){
String[] values = line.split(",");
Iterator<ArrayList<String>> iter = map.values().iterator ();
for (String value : values) {
if (iter.hasNext()) {
iter.next().add(value);
}
}
}

How can I add a string one at a time to a HashMap<Integer, List<String>>?

This function loops through a dictionary (allWords) and uses the
getKey function to generate a key. wordListMap is a HashMap> so I need to loop through and put the key and and a List. If there is not a list I put one if there is I just need to append the next dictionary word. This is where I need help. I just can't figure out the syntax to simply append the next word to the list that is already there. Any Help would be appreciated.
public static void constructWordListMap() {
wordListMap = new HashMap<>();
for (String w : allWords) {
int key = getKey(w);
if (isValidWord(w) && !wordListMap.containsKey(key)) {
List list = new ArrayList();
list.add(w);
wordListMap.put(key, list);
} else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
}
}
map.get(key).add(value)
Simple as that.
So I've gathered that you want to, given HashMap<Integer, List<String>>, you'd like to:
create a List object
add String objects to said List
add that List object as a value to be paired with a previously generated key (type Integer)
To do so, you'd want to first generate the key
Integer myKey = getKey(w);
Then, you'd enter a loop and add to a List object
List<String> myList = new List<String>;
for(int i = 0; i < intendedListLength; i++) {
String myEntry = //wherever you get your string from
myList.add(myEntry);
}
Lastly, you'd add the List to the HashMap
myHash.put(myKey, myList);
Leave any questions in the comments.
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
If you want to add a new value to your list, you need to retrieve that list first. In the code above, you are putting the return value of add into the table (which is a boolean), and that is not what you want.
Instead, you will want to do as Paul said:
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.get(key).add(w);
}
The reason this works is because you already added an ArrayList to the table earlier. Here, you are getting that ArrayList, and adding a new value to it.

Is there a way to store data into an array from an input file where the name of the array is given in the file?

I want to have an input file with a format like this:
ArrayName Value
where ArrayName is the name of the array that you want to store the value in.
Each line of input can be stored in a new or an existing array. The problem I have is that I don't know how to take the ArrayName from the file and create an array out of it. Or if the array already exists I'm not sure how to store the value into the array with that name.
I'm not sure why you would like to name your array from the file, maybe you can explain more about that. But meanwhile one thing you could do instead is:
1. Declare a HashMap of arrays in the form HashMap<String, int[]> (that is if your data are integers).
2. Read the name of the array from file and store its elements in the map using array name as the key.
Once you've done it, how will you know which array you've done it to? I suggest you use a Map<String, List<String>>.
Map<String, List<String>> map = new HashMap<>();
Then you can read the key from your file perhaps with a Scanner and clean up afterwards with try-with-resources like
try (Scanner s = new Scanner(new File(filePath))) {
Map<String, List<String>> map = new HashMap<>();
while (s.hasNextLine()) {
String line = s.nextLine();
String[] parts = line.split("\\s+");
String name = (parts.length > 1) ? parts[0] : "";
String value = (parts.length > 1) ? parts[1] : "";
List<String> al = map.get(name);
if (al == null) {
al = new ArrayList<>();
map.put(name, al);
}
al.add(value);
}
System.out.println(map); // <-- print the map.
} catch (Exception e) {
e.printStackTrace();
}

How to find all error messages and display them in descending order

Hi I am trying to sort input file from user for error messages in descending orders of occurrence.
input_file.txt
23545 debug code_to_debug
43535 error check your code
34243 error check values
32442 run program execute
24525 error check your code
I want to get output as
error check your code
error check values
My code currently:
import java.io.*;
import java.util.*;
public class Sort {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("fileToRead"));
Map<String, String> map=new TreeMap<String, String>();
String line="";
while((line=reader.readLine())!=null){
map.put(getField(line),line);
}
reader.close();
FileWriter writer = new FileWriter("fileToWrite");
for(String val : map.values()){
writer.write(val);
writer.write('\n');
}
writer.close();
}
private static String getField(String line) {
return line.split(" ")[0];//extract value you want to sort on
}
}
Change your mapping from <String, String> to <Integer, String>. Then, use a custom Comparator to compare the Integers from least to greatest.
It appears that your error messages are ranked by an integer value from most severe to least severe. This should allow you to use that fact.
Rather than having a Map<String,String> where the key is the integer value you could have the key as the error message and then the value could hold a list of the integer values so when reading the file it would become something like and also implement a comparator in the map to order them:
Map<String, String> map = new TreeMap<String, List<String>>(new Comparator<String>()
{
#Override
public int compare(String s1, String s2)
{
//Implement a compare to get the order of string you want
}
}
);
String line = "";
while((line = reader.readLine()) != null)
{
String lineStr = line.split(" ")[1]; // get the message
List<String> vals = map.get(lineStr) // get the existing list
if( vals == null)
vals = new ArrayList<String>(); // create a new list if there isn't one
vals.add(getFeild(line)); // add the int value to the list
map.put(lineStr,vals); // add to map
}
You could then sort the list into numeric order if you wanted. Also this would then require a bit more work to print out the map - but this depends on the format
If all you want to do is reorder the input so all the error messages appear at the top, a very simple way to do it is like the following:
static String[] errorsToTop(String[] input) {
String[] output = new String[input.length];
int i = 0;
for(String line : input) {
if(line.contains("error"))
output[i++] = line;
}
for(String line : input) {
if(!line.contains("error"))
output[i++] = line;
}
return output;
}
That just copies the array first starting with all errors messages, then will all non-error messages.
It's also possible to make those two loops a nested loop though the logic is less obvious.
static String[] errorsToTop(String[] input) {
String[] output = new String[input.length];
int i = 0;
boolean not = false;
do {
for(String line : input) {
if(line.contains("error") ^ not)
output[i++] = line;
}
} while(not = !not);
return output;
}
It's unclear to me whether the numbers appear in your input text file or not. If they don't, you can use startsWith instead of contains:
if(line.startsWith("error"))
You could also use matches with a regex like:
if(line.matches("^\\d+ error[\\s\\S]*"))
which says "starts with any integer followed by a space followed by error followed by anything or nothing".
Since no answer has been marked I'll add 2 cents.
This code below works for exactly what you posted (and maybe nothing else), it assumes that errors have higher numbers than non errors, and that you are grabbing top N of lines based on a time slice or something.
import java.util.NavigableMap;
import java.util.TreeMap;
public class SortDesc {
public static void main(String[] args) {
NavigableMap<Integer, String> descendingMap = new TreeMap<Integer, String>().descendingMap();
descendingMap.put(23545, "debug code_to_debug");
descendingMap.put(43535, "error check your code");
descendingMap.put(34243, "error check values");
descendingMap.put(32442, "run program execute");
descendingMap.put(24525, "error check your code");
System.out.println(descendingMap);
}
}
results look like this
{43535=error check your code, 34243=error check values, 32442=run program execute, 24525=error check your code, 23545=debug code_to_debug}

use first token in a string to create separate array lists, second token will

I'm writing Java code. I have files that looks like:
President and Vice-President ==> Fred Flinestone(P)
US Senate ==> Louise Moon (P)
Proposition #1 ==> Yes
Amendment #1 ==> Decline
I am trying to separate the different contest (President and Vice-President, US Senate, etc.) from the "voter's choice" (Alvin Boone..., Louise, etc) line by line. I want to use the first token to create an array list and the second token to be added to the corresponding array list.
I hope I am not over my head with this as I am a new Java programmer but all help is appreciated. So far I have.
public void go () {
getContest();
}
void getContest() {
// reading file and call the addContest() method for each line/
try {
String line = null;
while ((line = reader.readLine()) != null) {
addContest(line);
}
}
}
void addContest (String lineToParse) {
String[] tokens = lineToParse.split(">");
// somehow this will add contests to
// its own array 0 is the first part of split
contestList.add(tokens[0]);
}
I hope I am not asking for too much but if I can find out how to create the array list I am sure I can put second token in the corresponding array. Thank you!
It looks like you would probably be better served by a map. The first element is the key, and the second element the value.
ArrayList<String> lines = new ArrayList<String>();
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
HashMap<String, String> votes = new HashMap<String, String>();
for(String line: lines) {
String[] terms = line.split(">");
votes.put(terms[0], terms[1]);
}

Categories

Resources