I have a project that I'm working on for my Java class (obviously) and I must have missed the lecture on how to interact with TreeMaps. I have no idea what I'm doing with this part and I'm not finding a lot of help from Google.
For the first case in the program, I have to print all values of a TreeMap. The following is the code I was provided and the work I have done with it. Everything in case A is mine, but it isn't working. Any help would be appreciated.
import java.util.Scanner;
import java.util.Set;
import java.util.Map;
import java.util.TreeMap;
import java.io.File;
import java.io.FileNotFoundException;
public class prog7 {
public static void main(String args[])
throws FileNotFoundException
{
Scanner kb=new Scanner(System.in);
/*here, add code to declare and create a tree map*/
TreeMap treeMap = new TreeMap();
/*here, add code to declare a variable and
let it be the key set of the map
*/
String key;
//temporary variables
String tempWord;
String tempDef;
//the following code reads data from the file glossary.txt
//and saves the data as entries in the map
Scanner infile=new Scanner(new File("glossary.txt"));
while(infile.hasNext())
{
tempWord=infile.nextLine();
tempDef=infile.nextLine();
/*here, add code to add tempWord and tempDef
as an entry in the map
*/
treeMap.put(tempWord, tempDef);
}
infile.close();
while(true)
{
System.out.println();
System.out.println();
//show menu and prompt message
System.out.println("Please select one of the following actions:");
System.out.println("q - Quit");
System.out.println("a - List all words and their definitons");
System.out.println("b - Enter a word to find its definition");
System.out.println("c - Add a new entry");
System.out.println("d - Delete an entry");
System.out.println("Please enter q, a, b, c or d:");
String selection=kb.nextLine(); //read user's selection
if (selection.equals("")) continue; //if selection is "", show menu again
switch (selection.charAt(0))
{
case 'q':
System.out.println("\nThank you.");
return;
/*write code for the cases 'a','b','c' and 'd'
so that the program runs as in the sample run
*/
case 'a':
for (String treeKey : treeMap.keySet())
System.out.println(treeKey);
break;
Iterate over the entrySet rather than the keySet. You get a set of Map.Entry<K, V> which have convenient getKey() and getValue() methods.
That said, Java's standard Map implementations have an implementation of toString() that does what you want. Of course, I reckon you'll only get points for reimplementing it, not for cleverly avoiding it...
for (Map.Entry<K, V> entry : myMap.entrySet()) {
System.out.println("Key: " + entry.getKey() + ". Value: " + entry.getValue());
}
You can use entrySet(). Every Map in java have this method.
Map<String, String> tree = new TreeMap<String, String>();
tree.put("param1", "value1");
tree.put("param2", "value2");
for (Entry<String, String> entry : tree.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.printf("%s : %s\n", key, value);
}
for (String treeKey : treeMap.keySet())
That gives you the keys.
Now in that loop, get each value from the treeMap using the key (treeKey), and print it.
You can use treeMap.get(treeKey) inside your loop to get the value for the key. Since this value is a string, you could just do something like:
System.out.println("The value for the current key is " + (String)treeMap.get(treeKey));
With Java 8+ there is no need for a loop: lambda expressions enable you to print all keys and/or values in a neat one-liner:
map.forEach((key, value) -> System.out.println(key + " " + value));
Iterating over the set of keys and then retrieving each value is less efficient than iterating over the set of entries (getEntries()). In the former case, getValue() will have to perform a new lookup each time, while getEntries() can simply return the entire contents of the map.
Static analysers such as FindBugs will give you a warning if you try to retrieve a value inside a iteration over the map's keys.
not specifically about TreeMaps, but about Maps in general - I like this first answer, using Guava: Convert java Map to custom key=value string
Related
This question already has answers here:
Increment an Integer within a HashMap
(13 answers)
Closed 10 months ago.
I'm new to HashMaps, and I was wondering if there was a way to add values together if they have the same key.
For example, when I have the key 'a' and the value is 20 and later on I use the key 'a' again and the value is 10 the value should now be 30.
I don't know how I would check if the Value already is in the HashMap and then use the same value again. The adding part could be done with just a variable that copies the current value and adds the new one, I guess.
I am guessing you want a hashmap for character vs integer and want to add the integer to already present value in case the value is present.You can do something like below:
public hashMapImpl(char ch, int number){
Map<Character,Integer> map = new HashMap<>();
if(map.containsKey(ch)){
map.put(ch, map.get(ch)+number);
}
else{
map.put(ch,number);
}
}
Where ch will be your key and number will be something that you want to store at particular key.
you can use compute method to add/sum a value in case a key exists, or create a new entry in case it doesn't.
Map<String, Integer> map = new HashMap<>();
String myKey = "a";
Integer myValue = 10;
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
Outputs:
a={10}
a={20}
Of course, putting this compute logic inside a method will make you code cleaner :)
I will use an example class called HashMapExamle to explain this.
Inside the class I will create a HashMap called bigHashMap assuming that was your initial hashMap with prior data.
I also have a main method to call the method that will solve your problem. I have named the method bigHashMap. So for starters, i have initialized our prior HashMap named bigHashMap and initialized wit with some new key-value pairs.
I will printout the value of the HashMap. I will then add a value with the same key, in this case food with the value 15, by calling the hashMapValueAdd method I have created and passing the key(food) and value(15) to it.
The concept of the method is:
Check if the HashMap contains the key.
if it has it, it will get the value with that ky and add the new value to it. it will then replace the value at the key with the new value.
If the key is not found in the hashmap then the new key-value pair will just be inserted.
class HashMapExample {
private static HashMap<String, Integer> bigHashMap;
public static void main(String[] args) {
bigHashMap = new HashMap<>();
// Add test data
bigHashMap.put("food", 200);
bigHashMap.put("transport", 20);
bigHashMap.put("entertainment", 40);
System.out.println("Data before : \n" + bigHashMap);
hashmapValueAdd("food", 15);
System.out.println("Data after : \n" + bigHashMap);
}
private static void hashmapValueAdd(String key, int value) {
// Check if hashMap contains the given key
if (bigHashMap.containsKey(key)) {
// Get previous value with the same key
int valueWithSameKey = bigHashMap.get(key);
// Increment the value with incoming value
int newValue = valueWithSameKey + value;
// Put updated value into HashMap
// bigHashMap.put(key, +value);
bigHashMap.replace(key, newValue);
} else {
// Put the current key since it does not exist in the HashMap
bigHashMap.put(key, value);
}
}
}
I hope this solves your problem.
You can check out these HashMap explanations to get a better understanding.
Java HashMap - W3Schools
Java MAp - Jakob Jenkov
Java HashMap replace()
Update the Value Associated With a Key in a HashMap
I am trying out creating an in-memory database solution. Either HashMap or TreeSet. I know how I can search for a value using contains, and if this was a normal database situation this would be easier. But if I'm trying to search for a value by case-insensitive or a numerical value that is either greater or less than, how would I go about that in this case?
Here is my last name method, but it is just a simple contains, if it is is case insensitive it's not found
case 4:
Scanner input4 = new Scanner(System.in);
System.out.println("Search Last Name ");
String retLn = input4.nextLine();
if(employeeKey.containsKey(retLn))
{
EmpManager searchedEmp = employeeKey.get(retLn);
System.out.println(searchedEmp);
System.out.println("");
}
else
{
System.out.println("No Last Name Found");
System.out.println("");
}
You may use a TreeMap with Custom Comparator.
When you want a case-insensitive comparison:
new TreeMap<String,V>(String.CASE_INSENSITIVE_ORDER);
When you want an Integer based comparison:
new TreeMap<Integer,V>(Comparator.naturalOrder());
Or just use default comparator:
new TreeMap<Integer,V>();
For finding all entries greater or lesser than a value use headMap(), tailMap() or subMap()
You can override the containsKey() method in your HashMap definition.
For example:
HashMap<String, Integer> map = new HashMap<String, Integer>() {
#Override
public boolean containsKey(Object key) {
for (String s : this.keySet()) {
String keyString = (String) key;
if (keyString.equalsIgnoreCase(s))
return true;
}
return false;
}
};
As per your current solution, just ensure whenever you're adding to the Map that you turn the keys to lowerCase to make it case-insensitive, which then makes it easier to compare against user input later on e.g.
if(employeeKey.containsKey(retLn.toLowerCase())) // considering the keys inside the map are all lowercase
if you later want to search based on some given range, then you could do this:
map.forEach((key, value) -> {
if(key.equalsIgnoreCase(retLn) && value > someValue && value < someValue){
// access the value here
}
});
I have a text file which has lines of animals, who occur on this list from 1 to n times. I need to read this text file, count all the separate animal occurences, sort them from highest to lowest and put them in a jtable.
For example, the text file looks like this:
dog
sheep
cat
horse
cat
tiger
cat
cat
tiger
I need to count all the same occurences like so:
dog 1
sheep 1
cat 4
horse 1
tiger 2
And then sort them from highest to lowest and somehow put them into a table, so that would be:
Animal name: count
cat 4
tiger 2
dog 1
sheep 1
horse 1
So, for now my specific question is how can i count the matches for all the separate animals?
Thanks for the help!
EDIT
The answer provided by Vishal Kamat, has worked, my animals and their occurences have been counted with this code:
java hashmap word count from a text file
Now, I just need to put all this information to a new jtable
Just use the switch-case. You can use a counter for each animal. Or use an arrayList where you can store the amount of each animal...
String line = reader.readLine();
while (line != null) {
switch (line) {
case "cat":
catCounter++;
break;
case "dog":
dogCounter++;
break;
case "horse":
horseCounter++;
break;
case "tiger":
tigerCounter++;
break;
case "sheep":
sheepCounter++;
break;
default:
break;
}
}
Unfortunately I'm not able to write and test a code, but I am able to give you a path to do the thing you want.
You can use Regex for matching how many times, let's say "cat" was mentioned in the text file.
Perhaps this would help: http://code.runnable.com/UqUJWzqM7L8-AAFT/how-to-count-the-number-of-matching-string-in-java-for-regex
I did not write the code, credits to Mirang.
You can have a Map<String, Integer> where key would be the animal name and count would be the occurances so far. Everytime you read an animal, get the value from the map and increment it. Finally you can sort the Map using the integer value of the count and store in the table.
You can try this.if it is convenient to you.
HashMap map=new HashMap();
HashSet set=new HashSet();
FileInputStream fis=new FileInputStream(file);
StreamTokenizer st=new StreamTokenizer(fis);
while(st.nextToken()!=StreamTokenizer.TT_EOF){
Integer count=1;
String s;
switch(st.ttype)
{
case StreamTokenizer.TT_WORD:
s=st.sval;
if(map.containsKey(s))
{
count=(Integer)map.get(s);
count++;
map.put(s,count);
set.add(s);
}
else
{
map.put(s,count);
set.add(s);
}
break;
}
}
//now you have a collection of words with their frequency.it will automatically sort numeric values
System.out.println("frequency of each word in file");
Iterator iter=set.iterator();//get all the keys from the HashSet
//display them with help of Iterator interface
while(iter.hasNext())
{
String s=(String)iter.next();
Integer count=(Integer)map.get(s);
System.out.println("frequency of "+s+" : "+count);
}
Most of the answers here are either too complicated or don't implement frequency distribution properly. Following is my solution:
Map<String, Integer> frequency = new HashMap<>();
try (Scanner scanner = new Scanner(new File("path/to/file"), "UTF-8")) {
while (scanner.hasNext()) {
String temp = scanner.nextLine();
if(frequency.containsKey(temp)) {
Integer count = frequency.get(temp);
frequency.put(temp, Integer.sum(count, 1));
} else {
frequency.put(temp, 1);
}
}
}
The key of the Map contains the animal name and value (which is an Integer) contains the occurrences of the animal names read so far. After each iteration, check if the animal name is in the key. If yes, increment its value. Otherwise, put a new key-value pair with the value as 1. Once the Map has been populated, you can use it as you please.
You can do this with Java 8 Streams. This solution is compact and quite expressive. It creates a Stream of lines read from the file. Each unique line becomes a group, it counts the entries in each group, and then sorts the groups by their value, in descending order.
Now since you want to put these in a JTable, you need a two dimentional array.
package com.test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.JTable;
public class TestCount {
public static void main(String args[]) throws URISyntaxException, IOException {
// for absolute path use: Paths.get("/path/to/animals.txt")
try (Stream<String> stream = Files.lines(Paths.get(TestCount.class.getClassLoader().getResource("animals").toURI()))) {
Object[][] data = stream
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map((entry) -> new Object[] { entry.getKey(), entry.getValue() })
.toArray(Object[][]::new);
// print the data
for (Object[] row : data) {
System.out.println(Arrays.toString(row));
}
// create the JTable
new JTable(data, new String[] { "animal", "count" });
}
}
}
If you already have a sorted Map you can covert to a two dimensional array like so:
Object[][] data = m1.entrySet().stream()
.map((entry) -> new Object[] { entry.getKey(), entry.getValue() })
.toArray(Object[][]::new);
This question already has answers here:
Finding the smallest and second smallest value in an array Java
(3 answers)
Closed 8 years ago.
For my programming class I need to write a method where the code prints the fastest and the second fastest runner.
This is what I've got:
import java.util.Arrays;
class Marathon {
public static void main (String[] arguments){ `
`String[] names ={
"Alex", "Clair", "Sarah", "Andy", "Anna", "Bob"
};
int[] times ={
341, 273, 278, 329, 445, 402,
};
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]+ ": " + times[i]);
}
}
}
How do I get it to show only the fastest person (lowest number) and the second fastest person (second lowest number).
Here's one way to find the fastest runner
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
class Marathon {
public static void main (String[] arguments){
HashMap<String, Integer>namez = new HashMap<String, Integer>();
namez.put("Alex", 341 );
namez.put("Clair",273 );
namez.put("Sarah",278);
namez.put("Andy",329);
namez.put("Anna",445 );
namez.put("Bob",402);
Integer min = Collections.min(namez.values());
namez.containsValue(min);
for (Entry<String, Integer>entry: namez.entrySet()){
if(entry.getValue()==min){
System.out.println(entry.getKey()+": "+entry.getValue());
String key = entry.getKey();
}
}
}
}
EDIT: Here is actually the way that finds fastest and the second fastest person from your list. It only outputs their names, which are Clair and Sarah. I hope it helps.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
class Marathon {
public static void main (String[] arguments){
HashMap<Integer, String>namez = new HashMap<Integer, String>();
namez.put(341,"Alex");
namez.put(273,"Clair");
namez.put(278, "Sarah");
namez.put(329,"Andy");
namez.put(445,"Anna");
namez.put(402, "Bob");
ArrayList<Integer> timez = new ArrayList<Integer>();
timez.add(341);
timez.add(273);
timez.add(278);
timez.add(329);
timez.add(445);
timez.add(402);
Collections.sort(timez);
System.out.println(namez.get(timez.get(0)));
System.out.println(namez.get(timez.get(1)));
}
}
This is probably the most compact way to do it:
import java.util.*;
public class Main {
public static void main(String[] args) {
//Create the mapping:
TreeMap<Integer, String> timeToNameMapping = new TreeMap<Integer,String>();
timeToNameMapping.put(341, "Alex");
timeToNameMapping.put(273, "Clair");
timeToNameMapping.put(278, "Sarah");
timeToNameMapping.put(329, "Andy");
timeToNameMapping.put(445, "Anna");
timeToNameMapping.put(402, "Bob");
//Get the keys from the above mapping.
//Since it is a TreeMap, the keys are sorted
List<Integer> times = new ArrayList<>(timeToNameMapping.keySet());
//Print the result
System.out.println("First: " + timeToNameMapping.get(times.get(0)));
System.out.println("Second: " + timeToNameMapping.get(times.get(1)));
}
}
Output:
First: Clair
Second: Sarah
Explanation:
I am using the reverse mapping, as this enables you to just sort all the keys, and then map the first two elements of the sorted list to the names in the TreeMap (given a runtime the TreeMap above will tell you the name of the runner for that time). TreeMaps are already ordered, but since they keys in the Map are in a TreeSet we cannot use index on it to get the two first elements. That is why I convert the keySet() to an ArrayList (which allows for indexing).
To elaborate on dictionaries (Maps):
Generally when using Lists you use the get() method to get a specific element. For Lists like ArrayList and LinkedList the get() method takes an integer (an index value) and returns the element that are at that position in the list.
Maps are a bit different: Maps make a correlation between a key and a value. In the above example if I give the map the key 341, then it will give me the value "Alex". The get() method on a Map therefore takes a key of type K (in this case an Integer, but it can be any kind of object actually) and returns a value of type V (in this case a String, but can also be any object). The type of the key and value are determined when creating the Map (in this case K, V = Integer, String). The concept of telling the map exactly what types are being used are called generics.
You want to sort the array first and then print out the first two in the array. Because it is for your class I wont give you the code that you need but I gave you the perfect hint all you have to do is google how to sort the array and call on first two. Google Keyswords "Java Sort Array"
I have a program that takes the number of instances of a character in a string and then puts them into a HashMap. I have it working, but how do I alphabetize the HashMap. Here is my code:
import java.util.*;
import java.lang.*;
import javax.swing.JOptionPane;
import java.io.*;
public class CharacterCount
{
public static void main(String args[])
{
{
String s = JOptionPane.showInputDialog("Enter in any text.");
String str = s.replaceAll("[., ]", "");
String[] splitted = str.split("");
HashMap hm = new HashMap();
for (int i = 0; i < splitted.length; i++) {
if (!hm.containsKey(splitted[i])) {
hm.put(splitted[i], 1);
} else {
hm.put(splitted[i], (Integer) hm.get(splitted[i]) + 1);
}
}
for (Object word : hm.keySet()) {
if (word.equals("")) {
System.out.println("Spaces: " + (Integer) hm.get(word));
}
else {
System.out.println(word + ": " + (Integer) hm.get(word));
}
}
}
}
}
What do I need to add to make it alphabetize/reorganize the HashMap?
An HashMap is, by default, unsorted. This because its implementation can't rely on order of elements.
If you need a sorted map then you will have to look into a TreeMap which supplies the same interface as a HashMap but it's inherently sorted on keys according to their natural ordering (or a custom Comparator). Mind that a TreeMap doesn't allow ordering on values, so if you need to sort your data by value then you will have to build your own sorted collection.
This is usually done by taking the Map.Entry<K,V> entrySet() and then build a new SortedSet by following your ordering rules.
Most maps, including HashMap, make no promises about order of contents. Consider SortedMap, or maintaining both a hash map and a sorted list in parallel.
Difference between HashMap, LinkedHashMap and TreeMap