here is the sample code for saving key-values with hashmap :
HashMap<String, String> data = new HashMap<String, String>();
data.put("key", "value");
or if the order matters to you use linkedHashMap :
HashMap<String, String> data = new LinkedHashMap<>();
the usage is the same;)
Answer from SepJaPro2.4 on Stack Overflowhere is the sample code for saving key-values with hashmap :
HashMap<String, String> data = new HashMap<String, String>();
data.put("key", "value");
or if the order matters to you use linkedHashMap :
HashMap<String, String> data = new LinkedHashMap<>();
the usage is the same;)
Data Structure Logic:
Hashmaps are used to access the content via its key.
In this sample, I guess you are scanning 'tuples' one by one and each tuple is different from other, so you won't need to access an old tuple via it's key.
So here, I suggest you to create the model class suitable for the key-value pairs and store them in a list. You can push that list when you are done.
Sample model for tuple:
public class KeyValuePair {
private String key;
private String value;
public KeyValuePair(String key, String value) {
this.key = key;
this.value = value;
}
}
Sample List to store:
List<KeyValuePair> keyValuePairList = new ArrayList<>();
keyValuePairList.add(new KeyValuePair("0", "816444014066"));
keyValuePairList.add(new KeyValuePair("1", "747083010945"));
keyValuePairList.add(new KeyValuePair("2", "816444010969"));
Storing:
If you cannot pass the data between activities, check out SQLite. You can store the data in SQLite and fetch it when needed. It is an offline database works on Android devices. You can delete the data when pushed to upstream.
Edit:
If the keys are the orders, you can simply use a String List like this:
List<String> keyValuePairList = new ArrayList<>();
keyValuePairList.add("816444014066");
keyValuePairList.add("747083010945");
keyValuePairList.add("816444010969");
How to refactor this Java code so it creates a String List of key:value pairs as opposed to printing them out?
java - Parsing a string with named sections and a key-value pair on each line - Code Review Stack Exchange
regex - How to search a string of key/value pairs in Java - Stack Overflow
Java convert List of key/value strings to Map - Stack Overflow
Create a Pair class, that holds both the Integer and the String and then add multiple Pair objects to a List, which will be shuffled.
public class Pair {
private Integer integer;
private String string;
//accessors
}
Then:
List<Pair> list = new ArrayList<Pair>();
//...add some Pair objects to the list
Collections.shuffle(list);
You can keep the Map. The Map is designed to be looked up by key so I suggest you have a list of shuffled keys.
public Map<Integer, String> getQuestionOptionsMap() {
Map<Integer, String> map = new HashMap<>();
String[] answers = {null, answer1, answer2, answer3, answer4};
for (int i = 1; i < answers.length; i++)
if (answers[i] != null)
map.put(i, answers[i]);
List<Integer> order = new ArrayList<>(map.keySet());
Collections.shuffle(order);
Map<Integer, String> shuffled = new LinkedHashMap<>();
for (Integer key : order)
shuffled.put(key, map.get(key));
return shuffled;
}
Hello
So I saw some code online that I implemented into my program to sort a hashmap<String, int> based on the values of the integers, and it works successfully but only outputs the values, I need to store the values into a String list but don't understand the code well enough to do this and have been failing repeatedly, it is confusing me to have so many brackets.
If anyone could point me in the right direction that'd be helpful, I don't even know what to google to find out how to do this, thanks.
method:
https://paste.ofcode.org/jTtkBHeMV8bEmzYdLLASrG
Your current code is very good: it reads easily, it is properly indented and clean. I am sure one could come up with a complicated regular expression for parsing this String but using a StringReader like you have done is simple and effective. It is dynamic with regard to the number of elements to put in the map.
I only have a couple of comments:
You are trimming each line only to determine if they are blank with
if (s.trim().isEmpty()) { continue; // Skip empty line }If you expect lines to have spaces to trim then you could do it all the time.
Instead of having a
setMetricsmethod that takes a map, I would have aaddMetricmethod that adds a key/value pair into the map.public void addMetric(String key, String value) { metrics.put(key, value); }This way, you don't need to build the map yourself in the
whileloop.To prevent from
NullPointerException, it is a good idea to always initiaze maps and lists when they are in instance variables. You can do it inline like the following:public class NameMetrics { private String name; private Map<String, String> metrics = new HashMap<>(); }or in the default constructor.
- The variable
sinString s = reader.readLine();could have a better name, likeline. - The
while(true)loop with an explicit break works correctly, but it might be easier to follow with the traditional patternwhile ((line = reader.readLine()) != null) {.
With those couples changes, you can have:
BufferedReader reader = new BufferedReader(new StringReader(response));
NameMetrics current = null;
List<NameMetrics> result = new ArrayList<>();
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) {
continue; // Skip empty line
}
int cut = line.indexOf(':');
if (cut == -1) {
cut = line.indexOf('-');
if (cut == -1) {
continue;
}
current = new NameMetrics();
current.setName(line.substring(0, cut));
result.add(current);
} else if (current != null) {
current.addMetric(line.substring(0, cut), line.substring(cut + 1));
}
}
First, I'd like to point out that if are you storing this from your program and reading it back from a file later, you'd be better off Serializing it. But since you're being given this file, let's move on.
Infinite Loops
It's generally discouraged to use while(true) loops. It's not particularly bad (in fact it's sometimes better), but it's always best to look for an alternative for readability sake. Instead, let's use while ((line = reader.readLine()) != null).
Initializing variables as null
I also see you initialized a few variables as null, but that isn't necessary since it's implied for classes. (Also note primitive variables are implied as 0 during initialization).
Using the output format to your advantage
You also have a cut variable that gets the index of the tokens, and then skips the line if it's blank. However, we know that the output is always going to be grouped into three lines, and we always know what those lines are going to be. We also know the data you really want is going to be the first three characters for the name, and everything after the first five characters for the tokens. Let's use that and make everything clear!
Putting it all together
String response = restTemplate.getForObject(url, String.class);
BufferedReader reader = new BufferedReader(new StringReader(response));
NameMetrics current;
Map<String, String> metricsHolder;
List<NameMetrics> result = new ArrayList<>();
String name, load, peak;
String nameline;
while ((nameline = reader.readLine()) != null) {
name = nameLine.substring(0, 3);
load = reader.readLine().substring(5);
peak = reader.readLine().substring(5);
reader.readline(); //eat empty line
current = new NameMetrics();
metricsHolder = new HashMap<>(); //No need to repeat the stuff inside the diamond operator
metricsHolder.put("Load", load);
metricsHolder.put("Peak", peak);
current.setName(name);
current.setMetrics(metricsHolder);
result.add(current);
}
Handling varying keys and names
When there are a variable number of keys, we still know that they're all generally in the same format of the name followed dashes, then a list of key:value lines, then a blank line. We can still use this to our advantage as follows:
String name;
String[] mapValues;
final int KEY = 0, VALUE = 1;
String nameline, keyLine;
while ((nameline = reader.readLine().trim()) != null) { //Loop until the end of the file
name = nameLine.substring(0, nameLine.indexOf("-") + 1); //Plus because substring excludes last index
metricsHolder = new HashMap<>(); //No need to repeat the stuff inside the diamond operator
while (!(keyLine = reader.readLine().trim()).isEmpty()) { //Loop until block ends with an empty line
mapValues = reader.readLine().split(":"); //Split key:value format
metricsHolder.put(mapValues[KEY], mapValues[VALUE]);
}
current = new NameMetrics();
current.setName(name);
current.setMetrics(metricsHolder);
result.add(current);
}
I would parse the String into a map and then just check for the key:
String rawValues = "key1=value1;key2=value2;key3=value3";
Map<String,String> map = new HashMap<String,String>();
String[] entries = rawValues.split(";");
for (String entry : entries) {
String[] keyValue = entry.split("=");
map.put(keyValue[0],keyValue[1]);
}
if (map.containsKey("myKey")) {
return map.get("myKey");
}
Use String.split:
String[] kvPairs = "key1=value1;key2=value2;key3=value3".split(";");
This will give you an array kvPairs that contains these elements:
key1=value1
key2=value2
key3=value3
Iterate over these and split them, too:
for(String kvPair: kvPairs) {
String[] kv = kvPair.split("=");
String key = kv[0];
String value = kv[1];
// Now do with key whatever you want with key and value...
if(key.equals("specialkey")) {
// Do something with value if the key is "specialvalue"...
}
}
You can simply do:
Iterator<String> it = list.iterator();
while(it.hasNext()) {
map.put(it.next(), it.next());
}
This will be more efficient than using the get(index) method (in case the list implementation does not allow random access)
Here's a relatively neat way:
var map = IntStream.range(0, list.size() / 2).boxed()
.collect(Collectors.toMap(i -> list.get(i * 2), i -> list.get(i * 2 + 1)));
You can do this same thing with the Splitter API directly:
Map<String, String> result = Splitter.on(',')
.trimResults()
.withKeyValueSeparator(
Splitter.on('=')
.limit(2)
.trimResults())
.split(input);
you can add a number to say how many splits you want just add a 2 to split
import java.util.HashMap;
public class HelloWorld{
public static void main(String []args){
HashMap<String, String> holder = new HashMap();
String payload = "cossn=0, abc=hello/=world";
String[] keyVals = payload.split(", ");
for(String keyVal:keyVals)
{
String[] parts = keyVal.split("=",2);
holder.put(parts[0],parts[1]);
}
}
}
You seem to need some Maps rather than Lists. Check the Javadoc for Map implementations; the most common is HashMap, but there are sorted, concurrent, deterministically iterable implementations etc. available too.
ListObject: every key corresponds to a String value; key is a string itself
Map<String, String>
ListObject: every key corresponds to an array of Strings; key is a string itself
Map<String, String[]>
(or preferably Map<String, List<String>>)
ListObject: same deal but with two value fields per key.
Map<String, UserDefinedClassWithTwoFields>
Map<KeyType,ValueType> which is implemented by HashMap<KeyType, ValueType> and TreeMap<KeyType, ValueType>, among others -- HashMap is unordered and TreeMap is ordered.
Other useful Maps are LinkedHashMap which is like HashMap but iterates in insertion order, and com.google.common.collect.Maps in Guava which has a bunch of utility methods, and com.google.common.collect.ImmutableMap which is an immutable map implementation.
For your key corresponding to an array of strings, you might want to look at a Multimap which is a map with multiple values for a given key.