Reduce For loop in Map - java

This is my code:
package vvv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class test {
public static void main(String args[]){
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "demo");
map.put(20, "fdemo");
map.put(60, "gdemo");
map.put(500, "udemo");
map.put(8000, "odemo");
// etc
int b = 7999;
for(int i =1; i<=8000; i++)
{
if(i == b)
System.out.println(map.get(b));
}
}
}
I don't want to use a big "for loop" just to find a result from map, and in addition, I can't change a key in the map (for example I can't change 500 to 4).
What should I do to reduce my loop condition?

This would iterate over all the keys in the Map :
for (Integer key : map.keySet()) {
...
}
However, I don't see the point in your loop, since you only do something for a specific key (7999), so your loop can be reduced to:
System.out.println(map.get(b));
Changing a key is not something you can do with a single method. You have to first remove the old key, and then insert the new key, using the same value.
if (map.containsKey(500))
map.put(4,map.remove(500));

Use:
for (Integer theKey : map.keySet()) {
String val=map.get(thekey);
....
}
If your are just trying to check if some key exists or not ,you don't even need the loops, use map.containKey(some_key)
And you may need to pay attention that if your key is your customer class rather than primitive type, you need to override the equals() and hashCode() method, or , something bad will happen.

Try below code it will work fine. No need to iterate map you just use map.conytainsKey(key) method.
{
String tempString=null;
tempString=((map.containsKey(b)?map.get(b):" "));
System.out.println(tempString);
}
or you may also write like this
{
System.out.println((map.containsKey(b)?map.get(b):" "));
}

for (Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
if(b==key);
println entry.getValue();
}

Related

How to find the max number of an unique string element in a alphanumeric Array list in java

I have list that has alphanumeric elements. I want to find the maximum number of each elements individually.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Collect {
public static void main(String[] args) {
List<String> alphaNumericList = new ArrayList<String>();
alphaNumericList.add("Demo.23");
alphaNumericList.add("Demo.1000");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Test.01");
alphaNumericList.add("Test.02");
alphaNumericList.add("Test.100");
alphaNumericList.add("Test.99");
Collections.sort(alphaNumericList);
System.out.println("Output "+Arrays.asList(alphaNumericList));
}
I need filter only below values. For that I am sorting the list but it filters based on the string rather than int value. I want to achieve in an efficient way. Please suggest on this.
Demo.1000
Test.100
Output [[Demo.1000, Demo.12, Demo.12, Demo.23, Test.01, Test.02, Test.100, Test.99]]
You can either create a special AlphaNumericList type, wrapping the array list or whatever collection(s) you want to use internally, giving it a nice public interface to work with, or for the simplest case if you want to stick to the ArrayList<String>, just use a Comparator for sort(..):
package de.scrum_master.stackoverflow.q60482676;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.lang.Integer.parseInt;
public class Collect {
public static void main(String[] args) {
List<String> alphaNumericList = Arrays.asList(
"Demo.23", "Demo.1000", "Demo.12", "Demo.12",
"Test.01", "Test.02", "Test.100", "Test.99"
);
Collections.sort(
alphaNumericList,
(o1, o2) ->
((Integer) parseInt(o1.split("[.]")[1])).compareTo(parseInt(o2.split("[.]")[1]))
);
System.out.println("Output " + alphaNumericList);
}
}
This will yield the following console log:
Output [Test.01, Test.02, Demo.12, Demo.12, Demo.23, Test.99, Test.100, Demo.1000]
Please let me know if you don't understand lambda syntax. You can also use an anonymous class instead like in pre-8 versions of Java.
Update 1: If you want to refactor the one-line lambda for better readability, maybe you prefer this:
Collections.sort(
alphaNumericList,
(text1, text2) -> {
Integer number1 = parseInt(text1.split("[.]")[1]);
int number2 = parseInt(text2.split("[.]")[1]);
return number1.compareTo(number2);
}
);
Update 2: If more than one dot "." character can occur in your strings, you need to get the numeric substring in a different way via regex match, still not complicated:
Collections.sort(
alphaNumericList,
(text1, text2) -> {
Integer number1 = parseInt(text1.replaceFirst(".*[.]", ""));
int number2 = parseInt(text2.replaceFirst(".*[.]", ""));
return number1.compareTo(number2);
}
);
Update 3: I just noticed that for some weird reason you put the sorted list into another list via Arrays.asList(alphaNumericList) when printing. I have replaced that by just alphaNumericList in the code above and also updated the console log. Before the output was like [[foo, bar, zot]], i.e. a nested list with one element.
Check below answer:
public static void main(String[] args) {
List<String> alphaNumericList = new ArrayList<String>();
alphaNumericList.add("Demo.23");
alphaNumericList.add("Demo.1000");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Test.01");
alphaNumericList.add("Test.02");
alphaNumericList.add("Test.100");
alphaNumericList.add("Test.99");
Map<String, List<Integer>> map = new HashMap<>();
for (String val : alphaNumericList) {
String key = val.split("\\.")[0];
Integer value = Integer.valueOf(val.split("\\.")[1]);
if (map.containsKey(key)) {
map.get(key).add(value);
} else {
List<Integer> intList = new ArrayList<>();
intList.add(value);
map.put(key, intList);
}
}
for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
List<Integer> valueList = entry.getValue();
Collections.sort(valueList, Collections.reverseOrder());
System.out.print(entry.getKey() + "." + valueList.get(0) + " ");
}
}
Using stream and toMap() collector.
Map<String, Long> result = alphaNumericList.stream().collect(
toMap(k -> k.split("\\.")[0], v -> Long.parseLong(v.split("\\.")[1]), maxBy(Long::compare)));
The result map will contain word part as a key and maximum number as a value of the map(in your example the map will contain {Demo=1000, Test=100})
a. Assuming there are string of type Demo. and Test. in your arraylist.
b. It should be trivial to filter out elements with String Demo. and then extract the max integer for same.
c. Same should be applicable for extracting out max number associated with Test.
Please check the following snippet of code to achieve the same.
Set<String> uniqueString = alphaNumericList.stream().map(c->c.replaceAll("\\.[0-9]*","")).collect(Collectors.toSet());
Map<String,Integer> map = new HashMap<>();
for(String s:uniqueString){
int max= alphaNumericList.stream().filter(c -> c.startsWith(s+".")).map(c -> c.replaceAll(s+"\\.","")).map(c-> Integer.parseInt(c)).max(Integer::compare).get();
map.put(s,max);
}

Elegant solution for string-counting?

The problem I have is an example of something I've seen often. I have a series of strings (one string per line, lets say) as input, and all I need to do is return how many times each string has appeared. What is the most elegant way to solve this, without using a trie or other string-specific structure? The solution I've used in the past has been to use a hashtable-esque collection of custom-made (String, integer) objects that implements Comparable to keep track of how many times each string has appeared, but this method seems clunky for several reasons:
1) This method requires the creation of a comparable function which is identical to the String's.compareTo().
2) The impression that I get is that I'm misusing TreeSet, which has been my collection of choice. Updating the counter for a given string requires checking to see if the object is in the set, removing the object, updating the object, and then reinserting it. This seems wrong.
Is there a more clever way to solve this problem? Perhaps there is a better Collections interface I could use to solve this problem?
Thanks.
One posibility can be:
public class Counter {
public int count = 1;
}
public void count(String[] values) {
Map<String, Counter> stringMap = new HashMap<String, Counter>();
for (String value : values) {
Counter count = stringMap.get(value);
if (count != null) {
count.count++;
} else {
stringMap.put(value, new Counter());
}
}
}
In this way you still need to keep a map but at least you don't need to regenerate the entry every time you match a new string, you can access the Counter class, which is a wrapper of integer and increase the value by one, optimizing the access to the array
TreeMap is much better for this problem, or better yet, Guava's Multiset.
To use a TreeMap, you'd use something like
Map<String, Integer> map = new TreeMap<>();
for (String word : words) {
Integer count = map.get(word);
if (count == null) {
map.put(word, 1);
} else {
map.put(word, count + 1);
}
}
// print out each word and each count:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.printf("Word: %s Count: %d%n", entry.getKey(), entry.getValue());
}
Integer theCount = map.get("the");
if (theCount == null) {
theCount = 0;
}
System.out.println(theCount); // number of times "the" appeared, or null
Multiset would be much simpler than that; you'd just write
Multiset<String> multiset = TreeMultiset.create();
for (String word : words) {
multiset.add(word);
}
for (Multiset.Entry<String> entry : multiset.entrySet()) {
System.out.printf("Word: %s Count: %d%n", entry.getElement(), entry.getCount());
}
System.out.println(multiset.count("the")); // number of times "the" appeared
You can use a hash-map (no need to "create a comparable function"):
Map<String,Integer> count(String[] strings)
{
Map<String,Integer> map = new HashMap<String,Integer>();
for (String key : strings)
{
Integer value = map.get(key);
if (value == null)
map.put(key,1);
else
map.put(key,value+1);
}
return map;
}
Here is how you can use this method in order to print (for example) the string-count of your input:
Map<String,Integer> map = count(input);
for (String key : map.keySet())
System.out.println(key+" "+map.get(key));
You can use a Bag data structure from the Apache Commons Collection, like the HashBag.
A Bag does exactly what you need: It keeps track of how often an element got added to the collections.
HashBag<String> bag = new HashBag<>();
bag.add("foo");
bag.add("foo");
bag.getCount("foo"); // 2

Java, hashmap inside a hashmap

follow up from my question here: How To Access hash maps key when the key is an object
I wanted to try something like this: webSearchHash.put(xfile.getPageTitle(i),outlinks.put(keyphrase.get(i), xfile.getOutLinks(i)));
Wonder why my keys are null
here is my code:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import readFile.*;
public class WebSearch {
readFile.ReadFile xfile = new readFile.ReadFile("inputgraph.txt");
HashMap webSearchHash = new HashMap();
ArrayList belongsTo = new ArrayList();
ArrayList keyphrase = new ArrayList();
public WebSearch() {
}
public void createGraph()
{
HashMap <Object, ArrayList<Integer> > outlinks = new HashMap <Object, ArrayList<Integer>>();
for (int i = 0; i < xfile.getNumberOfWebpages(); i++ )
{
keyphrase.add(i,xfile.getKeyPhrases(i));
webSearchHash.put(xfile.getPageTitle(i),outlinks.put(keyphrase.get(i), xfile.getOutLinks(i)));
}
}
}
when I do System.out.print(webSearchHash); the output is {Star-Ledger=null, Apple=null, Microsoft=null, Intel=null, Rutgers=null, Targum=null, Wikipedia=null, New York Times=null}
However System.out.print(outlinks); gives me : {[education, news, internet]=[0, 3], [power, news]=[1, 4], [computer, internet, device, ipod]=[2]} Basically I want a hashmap to be a value of my key
You really shouldn't use a HashMap (or any mutable object) as your key, since it will destabilize your Map. Depending on what you're intending to accomplish, there may be a number of useful approaches and libraries, but using an unstable object as a Map key is asking for trouble.
So figured I just do this which gives exactly what I want:
for (int i = 0; i < xfile.getNumberOfWebpages(); i++ )
{
HashMap <Object, ArrayList<Integer> > outlinks = new HashMap <Object, ArrayList<Integer>>();
keyphrase.add(i,xfile.getKeyPhrases(i));
outlinks.put(keyphrase.get(i), xfile.getOutLinks(i));
webSearchHash.put(xfile.getPageTitle(i), outlinks);
}
Your problem is you are putting in null with this statement
webSearchHash.put(xfile.getPageTitle(i),outlinks.put(keyphrase.get(i), xfile.getOutLinks(i)));
lets break it down. a put is of the form
map.put(key,value)
so for your key you have getPageTitle(i). which is fine
for your value, you have the return value of
outlinks.put(keyphrase.get(i), xfile.getOutLinks(i))
according to the javadoc, a hashmap put returns the previous value that was associated with this key (in this case keyphrase.get(i)) or null if no value was previously associated with it.
Since nothing was previously associated with your key, it returns null.
So your statement effectively is saying
webSearchHash.put(xfile.getPageTitle(i),null);
http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html#put(K, V)

How to get the string with more ocurrences in a list

I have a List of Strings and I'm trying to have a method that tells me which String has more occurrences in the List.
Here is what I've done so far:
package codekata;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class OcurrenciasEnLista {
public static void main(String[] args) {
List<String> lista = new ArrayList<String>();
lista.add("test");
lista.add("foo");
lista.add("foo");
lista.add("foo");
lista.add("bar");
lista.add("crack");
moreOftenWord(lista);
}
private static void moreOftenWord(List<String> lista) {
Map<String, Integer> mapa = new HashMap<String, Integer>();
for (String palabra: lista)
addOrIncrementCount(mapa, palabra);
}
private static void addOrIncrementCount(Map<String, Integer> counters,
String toAdd) {
Integer currValue = counters.get(toAdd);
if (currValue == null)
counters.put(toAdd, 1);
else
{
counters.put(toAdd, currValue + 1);
}
}
}
What I don't know how to do is to return -the word- already in the moreOftenWord method.
Can anybody give me a clue on this?
The most common element in a list is called the "mode" of the list.
http://www.dreamincode.net/forums/topic/39745-get-mode-of-a-list/ is the first result for "mode of a list java" that looks relevant in case you want a code sample.
To get at the most common element after you've built your map of counters, you probably want to do something like
Map.Entry<String, Integer> mode = null;
for (Map.Entry<String, Integer> e : counters.entrySet()) {
if (mode == null || mode.value() < e.value()) {
mode = e;
}
}
// Most common string in mode.getKey()
This assumes that you redefine
Map counters
generically as
Map<String, Integer> counters
The Multiset data structure maintains a count of each element added to it. So you can remove all boilerplate code if you use this. Then all you need to do is iterate through the Multiset and find the element that has the max count.
Guava library has many such useful data structures and more.
In statistics, this is called the "mode" (as Mike's answer already explained). jOOλ is a library that supports mode() on streams. The following program:
System.out.println(
Seq.of("test", "foo", "foo", "foo", "bar", "crack")
.mode()
);
Yields:
Optional[foo]
(disclaimer: I work for the company behind jOOλ)

Get key from a HashMap using the value [duplicate]

This question already has answers here:
Java Hashmap: How to get key from value?
(39 answers)
Closed 5 years ago.
I want to get the key of a HashMap using the value.
hashmap = new HashMap<String, Object>();
haspmap.put("one", 100);
haspmap.put("two", 200);
Which means i want a function that will take the value 100 and will return the string one.
It seems that there are a lot of questions here asking the same thing but they don't work for me.
Maybe because i am new with java.
How to do it?
The put method in HashMap is defined like this:
Object put(Object key, Object value)
key is the first parameter, so in your put, "one" is the key. You can't easily look up by value in a HashMap, if you really want to do that, it would be a linear search done by calling entrySet(), like this:
for (Map.Entry<Object, Object> e : hashmap.entrySet()) {
Object key = e.getKey();
Object value = e.getValue();
}
However, that's O(n) and kind of defeats the purpose of using a HashMap unless you only need to do it rarely. If you really want to be able to look up by key or value frequently, core Java doesn't have anything for you, but something like BiMap from the Google Collections is what you want.
We can get KEY from VALUE. Below is a sample code_
public class Main {
public static void main(String[] args) {
Map map = new HashMap();
map.put("key_1","one");
map.put("key_2","two");
map.put("key_3","three");
map.put("key_4","four");
System.out.println(getKeyFromValue(map,"four"));
}
public static Object getKeyFromValue(Map hm, Object value) {
for (Object o : hm.keySet()) {
if (hm.get(o).equals(value)) {
return o;
}
}
return null;
}
}
I hope this will help everyone.
If you need only that, simply use put(100, "one"). Note that the key is the first argument, and the value is the 2nd.
If you need to be able to get by both the key and the value, use BiMap (from guava)
You have it reversed. The 100 should be the first parameter (it's the key) and the "one" should be the second parameter (it's the value).
Read the javadoc for HashMap and that might help you: HashMap
To get the value, use hashmap.get(100).
You mixed the keys and the values.
Hashmap <Integer,String> hashmap = new HashMap<Integer, String>();
hashmap.put(100, "one");
hashmap.put(200, "two");
Afterwards a
hashmap.get(100);
will give you "one"
if you what to obtain "ONE" by giving in 100 then
initialize hash map by
hashmap = new HashMap<Object,String>();
haspmap.put(100,"one");
and retrieve value by
hashMap.get(100)
hope that helps.
public class Class1 {
private String extref="MY";
public String getExtref() {
return extref;
}
public String setExtref(String extref) {
return this.extref = extref;
}
public static void main(String[] args) {
Class1 obj=new Class1();
String value=obj.setExtref("AFF");
int returnedValue=getMethod(value);
System.out.println(returnedValue);
}
/**
* #param value
* #return
*/
private static int getMethod(String value) {
HashMap<Integer, String> hashmap1 = new HashMap<Integer, String>();
hashmap1.put(1,"MY");
hashmap1.put(2,"AFF");
if (hashmap1.containsValue(value))
{
for (Map.Entry<Integer,String> e : hashmap1.entrySet()) {
Integer key = e.getKey();
Object value2 = e.getValue();
if ((value2.toString()).equalsIgnoreCase(value))
{
return key;
}
}
}
return 0;
}
}
If you are not bound to use Hashmap, I would advise to use pair< T,T >.
The individual elements can be accessed by first and second calls.
Have a look at this http://www.cplusplus.com/reference/utility/pair/
I used it here : http://codeforces.com/contest/507/submission/9531943

Categories

Resources