Java - Converting Defined Intergers to Name Value - java

Not sure how to phrase that but I have this:
In a
public class DefinedValues{
public static final int CommandGroupLength = 0x00000001;
}
I want a way of getting the String "CommandGroupLength" from value 0x00000001;
Is that possible?

do you want to access the name of the variable that has the value 0x00000001? than this is not possible:
public class DefinedValues {
public static final int CommandGroupLength = 0x00000001;
}
with Java8 it is technically possible to at least get the name of a variable via reflection, see Java Reflection: How to get the name of a variable?
you can achieve the same thing much easier with a Map, which contains Key-Value-Pairs.
Map<String,Integer> myMap= new HashMap<>();
myMap.put("CommandGroupLength", 0x00000001);
then you write a function which searches in the entrySet of the Map for all keys that have that value, since it is not ensured there is only one, it'll need to return a Collection or Array or something similar.
here's my code:
public static void main(String[] args) {
Map<String,Integer> myMap = new HashMap<>();
myMap.put("CommandGroupLength", 0x00000001);
myMap.put("testA", 5);
myMap.put("testB", 12);
myMap.put("testC", 42);
System.out.println("Searching for value 0x00000001 in myMap");
Set<String> searchResults = findKeyByValue(myMap, 0x00000001);
System.out.println("I found the following keys:");
boolean isFirst = true;
for(String result : searchResults) {
if(isFirst)
isFirst = false;
else
System.out.printf(", ");
System.out.printf("%s", result);
}
}
public static Set<String> findKeyByValue(Map<String, Integer> map, Integer value) {
Set<String> result = new HashSet<>();
if(value != null) {
Set<Entry<String, Integer>> entrySet = map.entrySet();
for(Entry<String, Integer> entry : entrySet) {
if(value.equals(entry.getValue())) {
result.add(entry.getKey());
}
}
}
return result;
}

Related

Linked HashMap - Iteration (Java) [duplicate]

This question already has answers here:
How do I efficiently iterate over each entry in a Java Map?
(46 answers)
Closed 3 years ago.
I'm trying to iterate through a Linked HashMap keySet however I am having difficulties in getting it to work.
Essentially I am searching the keySet to find a word, and another word. If the second word is immediately after the first word I wish to return true. This is the progress I have made so far.
for (String word : storedWords.keySet()) {
value0++;
if(word.equals(firstWord)){
value1 = value0;
}
if(word.equals(secondWord)){
value2 = value0;
}
int value3 = value2 - 1;
if(value1 == value3){
result = true;
break;
}
}
EDIT:
I've solved my problem and am thankful for all of those who helped. I apologise for making a post when there was a lot of information available on the website however I just lacked the understanding of the logic behind it.
You can avoid iterating over the whole keySet by storing the indices of each element in a separate map; then you can just test if both keys are present and have indices differing by 1. For convenience, encapsulate both maps into an object:
import java.util.*;
public class MapWithIndices<K, V> {
private final Map<K, V> map = new LinkedHashMap<>();
private final Map<K, Integer> indices = new HashMap<>();
public V get(K k) {
return map.get(k);
}
public V put(K k, V v) {
V old = map.put(k, v);
if(old == null) {
indices.put(k, indices.size());
}
return old;
}
public boolean areAdjacent(K k1, K k2) {
Integer i1 = indices.get(k1);
Integer i2 = indices.get(k2);
return i1 != null && i2 != null && i1 + 1 == i2;
}
}
You can add more Map methods (e.g. size) by delegating them to map. However, the remove method cannot be implemented efficiently since it requires recomputing all later indices. If removing from the map is required, an alternative data structure design should be considered; for example, indices can store the original insertion order of each key, and an order statistic tree can be used to count how many existing keys have a lower original-insertion-order.
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
I think this is sort of in line with what you started with. You might want to test the performance though.
import java.util.LinkedHashMap;
import java.util.Map;
class Testing {
Map<String, Integer> storedWords = new LinkedHashMap<>();
{
storedWords.put("One",1);
storedWords.put("Two",2);
storedWords.put("Three",3);
storedWords.put("Four",4);
storedWords.put("Five",5);
}
public static void main(String[] args) {
Testing t = new Testing();
String firstWord;
String secondWord;
firstWord = "Three";
secondWord = "Five";
System.out.println(t.consecutive(firstWord, secondWord)); // false
firstWord = "Two";
secondWord = "Three";
System.out.println(t.consecutive(firstWord, secondWord)); // true
}
public boolean consecutive(String firstWord, String secondWord) {
boolean foundfirst = false;
for (String word : storedWords.keySet()) {
if (!foundfirst && word.equals(firstWord)){
foundfirst = true;
continue;
}
if (foundfirst) {
if(word.equals(secondWord)){
return true;
} else {
foundfirst = false; // reset to search for the first word again
}
}
}
return false;
}
}

iterate, find and update value in nested Map<String, ?>

I have a YML file, which I parse to Map using yamlBeans library.
I don't know how deep the nested map goes.
for example:
key1:
key2: value1
key3:
key4: value2
key5: value3
I need to find a specific value in this map, update it, and write the map back to YML file (which I know how to do).
This is my code for updating the value, and it's working.
However, this is only iterating twice through the nested map, and I need it to iterate it for as long as needed:
static void updateYmlContent(Map<String, ?> ymlMap, String value, String... keys) {
boolean found = false;
for (Map.Entry entry : ymlMap.entrySet()) {
if (entry.getKey().equals(keys[0])) {
found = true;
for (Map.Entry subEntry : ((Map<?, ?>) entry.getValue()).entrySet()) {
if (subEntry.getKey().equals(keys[1])) {
subEntry.setValue(value);
break;
} else {
throwKeyNotFoundException(keys[1]);
}
}
break;
}
}
if (!found) {
throwKeyNotFoundException(keys[0]);
}
}
Use recursion and a depth counter to drop through each level of the map.
I didn't compile this, so it probably needs a little tweaking, but here's the basic idea:
static void updateYmlContent(Map<String, ?> ymlMap, String value, String... keys) {
int depth = 0;
findAndReplaceContent(ymlMap, value, keys, depth);
}
static void findAndReplaceContent(Map map, .......) {
if (map.containsKey(keys[depth]))
{
if (depth == keys.length - 1)
{
// found it
map.put(keys[depth], value);
// done
}
else
{
findAndReplaceContent(map.get(keys[depth]), value, keys, depth+1);
}
}
else
{
// throw key not found
}
}
If ymlMap is mutable, it should be of type Map<String, Object> (ideally), i belive you have checked it already.
#SuppressWarnings("unchecked")
static void updateYmlContent(Map<String, ?> ymlMap, String value, String... keys)
{
for (int i = 0, lastIndex = keys.length - 1; i <= lastIndex; i++)
{
String key = keys[i];
Object v = ymlMap.get(key);
if (v == null) // Assumed value is never null, if key exists
throw new /* KeyNotFound */ RuntimeException("Key '" + key + "' not found");
if (i < lastIndex)
ymlMap = (Map<String, Object>) v;
else
((Map<String, String>) ymlMap).put(key, value);
}
}
You can do it via one for loop, please see the example:
private static void updateYmlContent(Map<String, Object> map, String newValue, String... keys) {
for (int i = 0; i < keys.length; i++) {
if (i + 1 == keys.length) {
map.put(keys[i], newValue);
return;
}
if (map.get(keys[i]) instanceof Map) {
map = (Map<String, Object>) map.get(keys[i]);
} else {
throw new RuntimeException();
}
}
throw new RuntimeException();
}
Also please see how it is used:
public static void main(String[] keys) throws Exception {
Map<String, Object> ymlMap = new HashMap<>();
Map<Object, Object> nested1 = new HashMap<>();
Map<Object, Object> nested2 = new HashMap<>();
nested2.put("key3", "oldvalue1");
nested2.put("key4", "oldvalue2");
nested1.put("key2", nested2);
ymlMap.put("key1", nested1);
updateYmlContent(ymlMap, "new", "key1", "key2", "key3");
}

Is there a way to compare two objects in a List and combine their values that is most optimal?(Java)

Quick question. Suppose I have a function total (List list) and I have a MyObject class that have a String and an int displayed below and I want to compare two different object Strings in my total method. If they are the same, add the value on both of them. Otherwise, do nothing.
For example data is
{[Johanna, 200], [Jack, 205], [Johanna, 100], [Jack, 50]};
The output should look like
{[Johanna, 300], [Jack, 255]};
public static class MyObject {
int value;
String name;
public MyObject(String nm, int val)
{
name = nm;
value = val;
}
}
public void total(List<MyObject> list) {
List<MyObject> newList = new ArrayList<MyObject>();
Collections.sort(list);
Iterator<Order> ItrL = list.iterator();
int index = 0;
while(ItrL.hasNext())
{
MyObject compare = ItrL.next();
Iterator<MyObject> ItrR = list.listIterator(index);
index++;
while (cmp.name.equals(ItrR.next().name)))
newList.add(new MyObject(cmp.name, cmp.value + ItrR.value));
}
}
You can do summing and comparisons in parallel with no need to sort first using streams.
List<MyObject> newList = Arrays.asList(
new MyObject("Johanna", 200),
new MyObject("Jack", 205),
new MyObject("Johanna", 100),
new MyObject("Jack", 50)
);
Map<String,Integer> map =
newList.stream().parallel()
.collect(Collectors.groupingBy(mo -> mo.name,
Collectors.summingInt(mo -> mo.value)));
System.out.println("map = " + map);
There is no method that is "most optimal" as it depends on how big the data is. The problem seems suitable for map-reduce, but if you have like only 4 elements, then the overhead cost doesn't justify a real map reduce algorithm.
So anyway, here's one alternative that is pre-Java 8 (list doesn't need to be sorted first):
public static Map<String, Integer> total(List<MyObject> list) {
Map<String, Integer> result = new HashMap<String, Integer>();
for (MyObject myObject : list) {
Integer prevValue = result.get(myObject.name);
if (prevValue == null) {
result.put(myObject.name, myObject.value);
} else {
result.put(myObject.name, myObject.value + prevValue);
}
}
return result;
}
You can reduce from n^2 to n*(n/2) by using
for(int i = 0 ...
for(int j = i + 1 ...

I am trying to sort a HashMap by Value, but the results i am getting is pretty awkward. Can anyone help me identify the reasons for it [duplicate]

This question already has answers here:
TreeMap sort by value
(13 answers)
Closed 7 years ago.
This is the code to sort HashMap by Value.
public class LongestChain
{
public static void main(String[] args)
{
String words[] = new String[]{"a","b", "c", "ca","ba","bca","bda","bdca"};
System.out.println(longestChainOfWords(words));
}
public static int longestChainOfWords(String words[])
{
Map<String, Integer> map = new HashMap<String, Integer>();
for(String a:words)
{
map.put(a, a.length());
}
System.out.println(map);
Map sortedMap = sortByValue(map);
System.out.println(sortedMap);
return sortedMap.size();
}
public static Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap)
{
Map<String, Integer> sortedMap = new TreeMap<String, Integer>(new ValueComparator(unsortedMap));
sortedMap.putAll(unsortedMap);
return sortedMap;
}
}
class ValueComparator implements Comparator
{
Map<String, Integer> map;
public ValueComparator(Map<String, Integer> map)
{
this.map = map;
}
public int compare(Object keyA, Object keyB)
{
Comparable valueA = map.get(keyA);
Comparable valueB = map.get(keyB);
System.out.println(keyA+" keyA "); System.out.println(keyB+" keyB ");
return valueA.compareTo(valueB);
}
}
Output is like this. I was expecting 8 elements in sortedMap too. Why the behavior is like this?
{ca=2, bda=3, ba=2, b=1, c=1, a=1, bdca=4, bca=3}
{b=1, ca=2, bda=3, bdca=4}
4
Because you let the TreeMap think it sorts keys. And if the key is equal the no new value will be put inside. As you have 4 different values, so you can find 4 results in your list.
What you can do is improve the compare - method so equal values will be ordered by their keys:
class ValueComparator implements Comparator<String> {
Map<String, Integer> map;
public ValueComparator(final Map<String, Integer> map) {
this.map = map;
}
#Override
public int compare(final String keyA, final String keyB) {
final Integer valueA = this.map.get(keyA);
final Integer valueB = this.map.get(keyB);
System.out.println(keyA + " keyA ");
System.out.println(keyB + " keyB ");
final int compared = valueA.compareTo(valueB);
if (compared != 0) {
return compared;
} else {
return keyA.compareTo(keyB);
}
}
}

Calling a method (hashmap/ hashset) from one class on a string in another.

My code is:
public class Main{
public static void main(String[] args){
WordGroup wordgroupOne= new WordGroup ("You can discover more about a person in an hour of play than in a year of conversation");
WordGroup wordgroupTwo= new WordGroup ( "When you play play hard when you work dont play at all");
String[] quoteOne = wordgroupOne.getWordArray();
String[] quoteTwo = wordgroupTwo.getWordArray();
for (String words : quoteOne){
System.out.println(words);
}
for (String words : quoteTwo){
System.out.println(words);
}
}
}
WordGroup class:
import java.util.HashSet;
import java.util.HashMap;
public class WordGroup {
public String words;
public WordGroup (String getWords){
words = getWords.toLowerCase();
}
public String[] getWordArray(){
return words.split(" ");
}
public HashSet<String> getWordSet(){
HashSet<String> set = new HashSet<String>();
String[] p = getWordArray();
for (String items : p){
set.add(items);
}
System.out.println(set);
return set;
}
public HashMap<String, Integer> getWordCounts() {
HashMap<String, Integer> map = new HashMap<String, Integer>();
String[] q = getWordArray();
for (String stuff : q) {
Integer oldVal = map.get(stuff);
if (oldVal == null){
oldVal = 0;
}
map.put(stuff, oldVal+1);
}
System.out.println(map);
return map;
}
}
What I am trying to do is use the getWordSet() method using the two WordGroups and
iterate or loop over the HashSet returned and print the words from it.
Call getWordCounts() on the two WordGroups. Use keySet() to retrieve the set of keys. Loop over this set and print out the word and its count for both WordGroups.
Use the getWordSet() method to make complete set of all the words from both WordGroups.
Loop over the new HashSet to print a complete list of all words with the sum counts from each of the hashmaps.
I am struggling with all of these. Any help is much appreciated!!
If you want to create a combined list or set, you will have to merge the lists together and the maps together. I leave that exercise to you.
public static void main(String[] args)
{
WordGroup wg1 = new WordGroup(
"You can discover more about a person in an hour of play than in a year of conversation");
WordGroup wg2 = new WordGroup(
"When you play play hard when you work dont play at all");
wg1.processWord();
// iterate through all the distinct words
Set<String> dw1 = wg1.getDistinctWords();
for (String s : dw1)
{
System.out.println(s);
}
// use map entry to iterate through the entry set
Map<String, Integer> wc1 = wg1.getWordCounts();
for (Map.Entry<String, Integer> entry : wc1.entrySet())
{
if (entry != null)
{
// use stringbuilder to build a temp string
// instead of using +
StringBuilder sb = new StringBuilder();
sb.append(entry.getKey());
sb.append(": ");
sb.append(entry.getValue());
System.out.println(sb);
}
}
}
public class WordGroup
{
// as a class, made the results of the process private
private String originalWord;
// we declare generic versions of the Collections, instead of the specific
// implementation
private Set<String> distinctWords;
private Map<String, Integer> wordCounts;
public WordGroup(String s)
{
this.originalWord = s;
// here we declare and initialize the specific implementation
this.distinctWords = new HashSet<String>();
this.wordCounts = new HashMap<String, Integer>();
}
public void processWord()
{
List<String> toProcess = getWordList();
if (toProcess != null && !toProcess.isEmpty())
{
for (String s : toProcess)
{
// the set will automatically figure out if it should be in the
// set or not.
this.distinctWords.add(s);
// call the update or insert method
upsertString(s);
}
}
}
// this splits the string into a list
// you could probably use a utility class from guava or something to do this
// but i have coded a naive version
private List<String> getWordList()
{
List<String> splitList = new ArrayList<String>();
// check to see if there is anything there
if (this.originalWord != null && !this.originalWord.isEmpty())
{
String lowered = this.originalWord.toLowerCase();
String[] splits = lowered.split(" ");
if (splits != null)
{
int iSize = splits.length;
if (iSize > 0)
{
// basically create a string
for (int i = 0; i < iSize; i++)
{
splitList.add(splits[i]);
}
}
}
}
return splitList;
}
// helper method to see if we need to add to the count
private void upsertString(String s)
{
if (s != null && !s.isEmpty())
{
if (this.wordCounts != null)
{
// default to 1, if its an insert
Integer newCount = 1;
// if it already exists we want to update
if (this.wordCounts.containsKey(s))
{
Integer currentCount = this.wordCounts.get(s);
if (currentCount != null)
{
// update the count by 1
newCount += currentCount;
}
}
// insert the new item
// or overwrite, because it is the same key to the new count
this.wordCounts.put(s, newCount);
}
}
}
public String getOriginalWord()
{
return this.originalWord;
}
public void setOriginalWord(String originalWord)
{
this.originalWord = originalWord;
}
public Set<String> getDistinctWords()
{
return this.distinctWords;
}
public void setDistinctWords(Set<String> distinctWords)
{
this.distinctWords = distinctWords;
}
public Map<String, Integer> getWordCounts()
{
return this.wordCounts;
}
public void setWordCounts(Map<String, Integer> wordCounts)
{
this.wordCounts = wordCounts;
}
}

Categories