How to get they key and value of a LinkedHashMap randomly? - java

I'm trying to write a little vocabulary test. The LinkedHashMap vocabulary consists of vocabulary. They key is a french word and the value is an english word. I already have a GUI but I'm struggling to get a random french word from the vocabulary and its position to find out if the entered word is right. I tried to do it with an ArrayList but then I only get the value but I also need the key to show which word the person has to translate. Any help is appreciated.
LinkedHashMap<String, String> vocabulary = new LinkedHashMap<String, String>();
Random random = new Random();
int number = random.nextInt(ReadExcelFile.lastRowNumber);
String value = (new ArrayList<String>(vocabulary.values())).get(number);

Put the keys into a list, then pick a random one:
// Do once after loading (or changing)
List<String> keyList = new ArrayList<>(vocabulary.keySet());
Random random = new Random();
int number = random.nextInt(vocabulary.size());
String key = keyList.get(number);
String value = vocabulary.get(key);

You can go in the following way!
Map<String, String> myMap = new LinkedHashMap<String, String>();
myMap.put("Bonjour", "Hello");
myMap.put("moi", "me");
myMap.put("tue", "you");
List<String> val = new ArrayList<String>(myMap.values());
int randomIndex = new Random().nextInt(val.size());
String randomValue = val.get(randomIndex);
System.out.println(randomValue);

Related

prevent two objects in two identical lists from matching in java

I'm trying to make a program that randomly matches people in a list in order to figure out who is buying who a gift this year.
The problem I am running into is that certain people can't match up because they are married, for example, Deana and Pete can't match nor can Chris and Lindsay.
Here is what I have right now without trying to prevent these match ups.
Thank you,
String[] family = {"Jen", "Chris", "Lindsay", "Erica", "Deana", "Pete"};
ArrayList people = new ArrayList<String>();
for(int i = 0; i<family.length; i++){
people.add(family[i]);
}
int i=0;
while (i != family.length) {
int personTwo = (int) Math.floor(Math.random() * people.size());
String perTst = people.get(personTwo).toString();
if((family[i] != perTst)){
System.out.println(family[i] +" buys for " + people.get(personTwo));
people.remove(personTwo);
i++;
}
}
Just create a map of couples:
Map<String, String> couples = new HashMap<>();
couples.put("Deana", "Pete");
couples.put("Chris", "Lindsay");
Then update your if to check if they're a couple:
if(!family[i].equals(perTst)
&& !perTst.equals(couples.get(family[i]))
&& !family[i].equals(couples.get(perTst))) {
//...
}
One way to do that would be to create a map of people to a set of who they cannot be matched with. For example:
Map<String, Set<String>> notAllowed = new HashMap<>();
Set<String> deanaSet = new HashSet<>();
deanaSet.put("Pete");
Set<String> peteSet = new HashSet<>();
peteSet.put("Deana");
...
notAllowed.put("Deana", deanaSet);
notAllowed.put("Pete", peteSet);
Then you can just get the set of not allowed matches for each user and see if the person you're proposing adding is in the set of not allowed users.

HashMap values are changing without telling them to

I have a problem that I am unable to understand..
I am building a HashMap called wholeSetHistory.
I am building a HashMap with the same keys and values that wholeSetHistory has, called wholeSetHistoryT.
In a similar way I create two HashMaps called wholeSetRates, wholeSetRatesT
All HashMaps have this format HashMap<String, HashMap<String, Double>> .
I have this function that creates a train set
public void createTrainSet(HashMap<String, HashMap<String, Double>> wholeSetRates, HashMap<String, HashMap<String, Double>> wholeSetHistory){
for(String fbid : wholeSetHistory.keySet()){
ArrayList<String> locsBe = new ArrayList<>();
HashMap<String, Double> locss = wholeSetHistory.get(fbid);
HashMap<String, Double> locss2 = wholeSetRates.get(fbid);
for(String loc : locss.keySet()){
if(locss.get(loc)==1.0){
locsBe.add(loc);
}
}
ArrayList<Integer> randomNums = new ArrayList<>();
for(int i=0; i<2; i++){
Random rn = new Random();
int randomNum;
do{
int range = locsBe.size() - 1 + 1;
randomNum = rn.nextInt(range);
}while(randomNums.contains(randomNum));
randomNums.add(randomNum);
locss.put(locsBe.get(randomNum), 0.0);
locss2.put(locsBe.get(randomNum), 0.0);
wholeSetHistory.put(fbid, locss);
wholeSetRates.put(fbid, locss2);
}
randomNums.clear();
}
}
So, later on I am using it like this
(... creation of wholeSetHistory, wholeSetHistoryT, wholeSetRates, wholeSetRatesT)
System.out.println(wholeSetHistory.get("1"));//1
createTrainSet(wholeSetRatings, wholeSetHistory, nearUserIDWithVisitedTrueValues);
That means that I am passing to the function as paramater only wholeSetHistory
Although, later I
System.out.println(wholeSetHistory.get("1"));//2
System.out.println(wholeSetHistoryT.get("1"));//3
This is what happens:
The values that changes in wholeSetHistory changes in wholeSetHistoryT too!
For example, prints 2 and 3 are the same(!) and different from 1.
Any help is mych appreciated.
A reference points to a location in memory. If you add the same reference to two different data structures, altering the reference in one will also alter the other. They point to the same object in memory.

Generate Dynamic Menu and SubMenu from database

I have two tables in my database i.e. Menu and Sub_Menu... I have retrieved the data from those two tables using JOIN queries and it looks like this
`SELECT menu.menu_name AS menu_name, sub_menu.sub_menu_name FROM menu LEFT JOIN user_category ON menu.user_category_id = user_category.user_category_id LEFT JOIN sub_menu ON menu.menu_id = sub_menu.menu_id WHERE user_category.user_category_name = "Normal";`
After this what i have done is I have used LinkedHashMap<String, String> to store the results. Now, the problem rises here. When I print the output, the last value of the duplicate key is only displayed and others are omitted... What i want to display is a unique key with multiple values.. I have tried it using LinkedHashMap<String, ArrayList<String>> but can't get it right !!!
`
LinkedHashMap<String, ArrayList<String>> menuSubMenu = new LinkedHashMap<String, ArrayList<String>>();`
`ArrayList<String> subMenu = null;`
`String key = null;`
while (rs.next()) {
key = rs.getString("menu_name");
if (key.equals(rs.getString("menu_name"))) {
key = rs.getString("menu_name");
subMenu = new ArrayList<String>();
subMenu.add(rs.getString("sub_menu_name"));
} else {
subMenu = null;
}
menuSubMenu.put(key, subMenu);
}
Sorry but you code sample is a bit confusing but you can try this way:
LinkedHashMap<String, ArrayList<String>> menuSubMenu = new LinkedHashMap<String, ArrayList<String>>();
while(true){
String key = rs.getString("menu_name");
if(!menuSubMenu.containsKey(key)){
menuSubMenu.put(key, new ArrayList<String>());
}
menuSubMenu.get(key).add(rs.getString("sub_menu_name"));
}
Hope it helps
I'm going to guess that the problem is where you are putting the data into your map instead of where you take it out. You need to make certain that you are putting the array list back into the map after you create a new one and that you're pulling that array list back out the next time you encounter that word.
I have to agree The Thom You have to check for already existing entries in your Hashmap:
LinkedHashMap<String, ArrayList<String>> menuSubMenu = new LinkedHashMap<String, ArrayList<String>>();
while (rs.next()) {
final String key = rs.getString("menu_name");
final ArrayList<String> subMenu = menuSubMenu.get(key);
if (subMenu == null) {
subMenu = new ArrayList<String>();
menuSubMenu.put(key, subMenu);
}
subMenu.add(rs.getString("sub_menu_name"));
}

Treemap with <Integer, List>

I'm going count the most used words in a text and I want to make it this way just need little help how i'm gonna fix the Treemap..
this is how its look like now ...
TreeMap<Integer, List<String>> Word = new TreeMap<Integer, List<String>>();
List<String> TheList = new ArrayList<String>();
//While there is still something to read..
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (Word.containsKey(NewWord)) {
Word.put(HERE I NEED HELP);
} else {
Word.put(HERE I NEED HELP);
}
}
So what i wanna do is if the NewWord is in the list then add one on Integer(key) and if not Add the word to the next list.
Your type appears to be completely incorrect
... if you want a frequency count
You want to have your word as the key and the count as the value. There is little value in using a sorted collection, but it is many time slower so I would use a HashMap.
Map<String, Integer> frequencyCount = new HashMap<>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
Integer count = frequencyCount.get(word);
if (count == null)
frequencyCount.put(word, 1);
else
frequencyCount.put(word, 1 + count);
}
... if you want to key by length. I would use a List<Set<String>> This is because your word length is positive and bounded, and you want to ignore duplicate words which is something a Set is designed to do.
List<Set<String>> wordsByLength = new ArrayList<Set<String>>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
// grow the array list as required.
while(wordsByteLength.size() <= word.length())
wordsByLength.add(new HashSet<String>());
// add the word ignoring duplicates.
wordsByLength.get(words.length()).add(word);
}
All the examples above are correctly storing the count into a map, unfortunately they are not sorting by count which is a requirement you also have.
Do not use a TreeMap, instead use a HashMap to build up the values.
Once you have the complete list of values built you can then drop the entrySet from the HashMap into a new ArrayList and sort that array list by Entry<String,Integer>.getValue().
Or to be neater create a new "Count" object which has both the word and the count in and use that.
Dont do..
TreeMap<Integer, List<String>>
instead do,
TreeMap<String, Integer> // String represents the word... Integer represents the count
because your key (count) can be same sometimes where as the words will be unique...
Do it the other way around... keep reading the words and check if your map contains that word... If yes, increment the count, else add the word with count = 1.
Try this one
TreeMap<String, Integer> Word = new TreeMap<String,Integer>();
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (Word.containsKey(NewWord)) {
Word.put(NewWord,Word.get(NewWord)+1);
} else {
Word.put(NewWord,1);
}
}
The way to solve this in a time-efficient manner is to have two maps. One map should be from keys to counts, and the other from counts to keys. You can assemble these in different passes. The first should assemble the map from keys to counts:
Map<String, Integer> wordCount = new HashMap<String,Integer>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
wordCount.put(word, wordCount.containsKey(word) ? wordCount.get(word) + 1 : 1);
}
The second phase inverts the map so that you can read off the top-most keys:
// Biggest values first!
Map<Integer,List<String>> wordsByFreq = new TreeMap<Integer,List<String>>(new Comparator<Integer>(){
public int compare(Integer a, Integer b) {
return a - b;
}
});
for (Map.Entry<String,Integer> e : wordCount) {
List<String> current = wordsByFreq.get(e.getValue());
if (current == null)
wordsByFreq.put(e.getValue(), current = new ArrayList<String>());
current.add(e.getKey());
}
Note that the first stage uses a HashMap because we don't need the order at all; just speedy access. The second stage needs a TreeMap and it needs a non-standard comparator so that the first value read out will be the list of most-frequent words (allowing for two or more words to be most-frequent).
Try this out:
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
Scanner scanner = null;
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (map.containsKey(NewWord)) {
Integer count = map.get(NewWord);
// Add the element back along with incremented count
map.put(NewWord, count++);
} else {
map.put(NewWord,1); // Add a new entry
}
}

How to convert a Navigablemap to String[][]

I need to convert a navigable map to a 2d String array.Below given is a code from an answer to one of my previous question.
NavigableMap<Integer,String> map =
new TreeMap<Integer, String>();
map.put(0, "Kid");
map.put(11, "Teens");
map.put(20, "Twenties");
map.put(30, "Thirties");
map.put(40, "Forties");
map.put(50, "Senior");
map.put(100, "OMG OMG OMG!");
System.out.println(map.get(map.floorKey(13))); // Teens
System.out.println(map.get(map.floorKey(29))); // Twenties
System.out.println(map.get(map.floorKey(30))); // Thirties
System.out.println(map.floorEntry(42).getValue()); // Forties
System.out.println(map.get(map.floorKey(666))); // OMG OMG OMG!
I have to convert this map to a 2d String array:
{
{"0-11","Kids"},
{"11-20","Teens"},
{"20-30","Twenties"}
...
}
Is there a fast and elegant way to do this?
Best bet is just to iterate through the Map and create an array for each entry, the troublesome part is generating things like "0-11" since this requires looking for the next highest key...but since the Map is sorted (because you're using a TreeMap) it's no big deal.
String[][] strArr = new String[map.size()][2];
int i = 0;
for(Entry<Integer, String> entry : map.entrySet()){
// current key
Integer key = entry.getKey();
// next key, or null if there isn't one
Integer nextKey = map.higherKey(key);
// you might want to define some behavior for when nextKey is null
// build the "0-11" part (column 0)
strArr[i][0] = key + "-" + nextKey;
// add the "Teens" part (this is just the value from the Map Entry)
strArr[i][1] = entry.getValue();
// increment i for the next row in strArr
i++;
}
you can create two Arrays, one with the keys and one with the values in an "elegant way" then you can construct an String[][] using this two arrays.
// Create an array containing the values in a map
Integer[] arrayKeys = (Integer[])map.keySet().toArray( new Integer[map.keySet().size()]);
// Create an array containing the values in a map
String[] arrayValues = (String[])map.values().toArray( new String[map.values().size()]);
String[][] stringArray = new String[arrayKeys.length][2];
for (int i=0; i < arrayValues.length; i++)
{
stringArray[i][0] = arrayKeys[i].toString() + (i+1 < arrayValues.length ? " - " + arrayKeys[i+1] : "");
stringArray[i][1] = arrayValues[i];
}

Categories

Resources