i'm attempting to reorder an List of Maps in alphabetical order. i can see that the "name" String gets filled out with the appropriate value, but groupDataCopy is never updated. as far as i know, using the new operator and calling "put" will place the value in the Map. but I can see that on the following iteration, the ArrayList contains:
{name = null}
i don't know why i'm losing values in my Map List. here is the code:
private void sortByName() {
List<Map<String, String>> groupDataCopy = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> childDataCopy = new ArrayList<List<Map<String, String>>>();
int groupPos = 0;
int nextNamePos = 0;
String name = null;
while(groupPos<groupData.size()) {
//main loop
int groupDataComparison = 0;
name = null;
while(groupDataComparison<groupData.size()) {
//comparison traversal for group
if(!groupDataCopy.isEmpty()) { //if groupDataCopy has data
if(groupDataCopy.get(groupDataCopy.size()-1).get("name").compareTo(groupData.get(groupDataComparison).get("name")) > 0) { //if the last index of groupDataCopy is alphabetically after (or equal to) last chosen name
if(name==null || groupData.get(groupDataComparison).get("name").compareTo(name) < 0) {
name = groupData.get(groupDataComparison).get("name");
nextNamePos = groupDataComparison;
}
}
} else {
if(name==null || groupData.get(groupDataComparison).get("name").compareTo(name) < 0) {
name = groupData.get(groupDataComparison).get("name");
nextNamePos = groupDataComparison;
}
}
groupDataComparison++;
}
groupDataCopy.add(new HashMap<String, String>());
groupDataCopy.get(groupPos).put("name", name);
childDataCopy.add(new ArrayList<Map<String, String>>());
for(Map<String, String> data : childData.get(nextNamePos)) {
childDataCopy.get(groupPos).add(data);
}
groupPos++;
}
groupData = groupDataCopy;
childData = childDataCopy;
}
Comparator<Map<String, String> comparator = new Comparator<Map<String, String>()
{
public int compare(Map<String, String> o1, Map<String, String> o2)
{
return o1.get("name").compartTo(o2.get("name");
}
}
Collections.sort(groupData, comparator);
Try creating a Comparator that will let you use Collections.sort:
Something like:
Comparator<Map<String, String> comp = new Comparator<Map<String, String>()
{
public int compare(Map<String, String> o1, Map<String, String> o2)
{
//write code to compare values
}
}
After which you can simply do:
Collections.sort(groupData, comp);
Related
In order to defend against XSS attacks, I wrote a class that extends from HttpServletRequestWrapper and overrides the getParameterValues method, the code is shown below:
#Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameters = super.getParameterMap();
LinkedHashMap<String, String[]> map = new LinkedHashMap<>();
if (parameters != null) {
for (String key : parameters.keySet()) {
String[] values = parameters.get(key);
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
value = HtmlUtil.filter(value);
}
values[i] = value;
}
map.put(key, values);
}
}
return map;
}
I'm wondering if this piece of code could be transformed using Java Stream because I see a lot of if condition judgement and for loop.
Methods:StrUtil.hasEmpty and HtmlUtil.filter are come from here: Hutool
Any suggestions to improve the performance of this code are welcome.
Yes you can make elegent solution with streams plus map / filter but it will be re-allocating the memory footprint of the request data creating many new for objects for Map, N * Map.Entry, N * String[], and filtered strings and other intermediate steps.
Alternatively consider simplifying the logic of your existing loop just to fix each String[] value in place and return the existing map:
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameters = super.getParameterMap();
if (parameters != null) {
for (String[] values : parameters.values()) {
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
values[i] = HtmlUtil.filter(value);
}
}
}
}
return parameters;
}
#Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameters = super.getParameterMap();
LinkedHashMap<String, String[]> map = new LinkedHashMap<>();
if (parameters != null) {
map = parameters.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
v -> Arrays.stream(v.getValue())
.filter(val -> !StrUtil.hasEmpty(val))
.map(HtmlUtil::filter).collect(Collectors.toList()).toArray(new String[0]),
(x, y) -> y, LinkedHashMap::new
));
}
return map;
}
I have the issue that my loop does not break and returns the same value
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
while (value.iterator().hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
String verified = value.iterator().next().gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), value.iterator().next().getName());
}
}
}
The problem here is that the same value kets put in the map for every key (value.iterator().next().getName()) always returns the same string
I think the below would be a correct approach for your problem:
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<People> peopleIterator = value.iterator();
while (peopleIterator.hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
People people = peopleIterator.next();
String verified = people.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), people.getName());
}
}
}
You need to store the iterator in a variable.
Consider below simple code :
Collection<String> strings = new ArrayList<>();
strings.add("value1");
strings.add("value2");
strings.add("value3");
strings.add("value4");
while (strings.iterator.hasNext())
{
System.out.println(strings.iterator.next());
}
This will run infinitely and will only print value1, but if you modify the code as below :
Collection<String> strings = new ArrayList<>();
strings.add("value1");
strings.add("value2");
strings.add("value3");
strings.add("value4");
Iterator<String> stringIterator = strings.iterator();
while (stringIterator.hasNext())
{
System.out.println(stringIterator.next());
}
It runs smooth.
You can learn more about iterator here : https://www.geeksforgeeks.org/how-to-use-iterator-in-java/
ALso, I think as you are calling iterator twice without checking hasNext() on the second call, it can throw java.util.NoSuchElementException
You are calling next() twice on that iterator. That moves it ahead and picks up the name of the next People, which might not be verified.
I believe you just want to get the name if it's a verified Peple?
while (value.iterator().hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
Peple nextPeple = value.iterator().next();
String verified = nextPeple.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), nextPeple.getName());
}
}
}
}
Every time you call value.iterator() new Iterator object is created from scratch, pointing to a first element. To avoid it, store first result of calling it into local variable.
Iterator<Peple> it = value.iterator();
while(it.hasNext()){
// your remaiing code
}
This code works fine with the below input:
import java.util.*;
public class Test {
public static void main(String[] ar){
Map<String, People> entry1 = new HashMap<String , People>();
People people1 = new People("true","name1");
People people2 = new People("false","name2");
People people3 = new People("true","name3");
entry1.put("user1", people1);
entry1.put("user2", people2);
entry1.put("user3", people3);
Map<String, People> entry2 = new HashMap<String , People>();
People people4 = new People("true","name1");
People people5 = new People("false","name2");
People people6 = new People("true","name3");
entry2.put("user1", people4);
entry2.put("user2", people5);
entry2.put("user3", people6);
Map<String, Map<String, People>> map2 = new HashMap<String, Map<String,
People>>();
map2.put("set1",entry1);
map2.put("set2",entry2);
Collection<People> strings = new ArrayList<>();
strings.add(people1);
strings.add(people6);
strings.add(people5);
strings.add(people3);
strings.add(people2);
getKeysByValue(map2, strings);
}
public static Map<String, String> getKeysByValue(Map<String, Map<String, People>> map, Collection<People> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<People> it = value.iterator();
while (it.hasNext()) {
People people = it.next();
for (Map.Entry<String, Map<String, People>> entry : map.entrySet()) {
for (Map.Entry<String, People> entry1 : entry.getValue().entrySet()) {
String verified = people.getVerified();
System.out.println(verified);
System.out.println("Key : "+entry1.getKey() +" Value : "+entry1.getValue().getVerified());
if (verified.equals(entry1.getValue().getVerified())) {
stringStringMap.put(entry1.getKey(), people.getName());
}
}
}
}
System.out.println(stringStringMap);
return stringStringMap;
}
}
People.java
public class People {
String verified;
public People(String verified, String name){
this.verified = verified;
this.name = name;
}
public String getVerified() {
return verified;
}
public String getName() {
return name;
}
String name;
}
Try this:
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<Peple> iterator = value.iterator();
while (iterator.hasNext()) {
Peple p = iterator.next();
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
String verified = p.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), p.getName());
}
}
}
}
}
I want to concatenate to the value of one map to key of another map and add them into list.
Compare value on basis of key of first map to value of another map.
e.g:
map1= {37=core__error_code_based, 153=core__app_dialog, 123=core__date}
map2={copy_2=37,button_back=37,button_cancel=153,button_confirm=153}
My approach is in first loop i get the key of map1 and then in second loop iterate the map2 values on basis map1 key.
So that I get the value of map1 and key of map2 and later concatenate in string.
List<String> finalKey=new ArrayList<>();
Iterator<Map.Entry<String,String>> entrySet=map1.entrySet().iterator();
Iterator<Map.Entry<String,String>> pageKey=map2.entrySet().iterator();
while(entrySet.hasNext()){
Map.Entry<String,String> entry = entrySet.next();
Map.Entry<String,String> pageValue = pageKey.next();
while(entry.getKey()==pageValue.getValue()){
finalKey.add(entry.getValue()+"__"+pageValue.getKey());
}
}
I had tried using iterator and entryset to iterate through the both map but not succeed
{core__error_code_based__copy_2,core__error_code_based__button_back,core__app_dialog__button_confirm,core__app_dialog__button_cancel}
Well i achieved this using
public class translatekeyName {
static List<String> finalString = new ArrayList<>();
public static Map<String, String> initialMap() {
Map<String, String> map1 = new HashMap<>();
map1.put("37", "core__error_code_based");
map1.put("153", "core__app_dialog");
return map1;
}
public static Map<String, String> secondMap() {
Map<String, String> map2 = new HashMap<>();
map2.put("copy_2", "37");
map2.put("button_back", "37");
map2.put("button_cancel", "153");
map2.put("button_confirm", "153");
return map2;
}
public List<String> concatenateString(Map page, Map source) {
Map<String, String> moduleKey = page;
Map<String, String> pageKey = source;
List<String> temp;
Iterator<Map.Entry<String, String>> entrySet = page.entrySet().iterator();
Iterator<Map.Entry<String, String>> pageKeyset = source.entrySet().iterator();
for (String value : moduleKey.keySet()) {
temp = getallKeys(source, value);
String tempValue = moduleKey.get(value);
for (int i = 0; i < temp.size(); i++) {
tempValue += "__" + temp.get(i);
finalString.add(tempValue);
}
}
return finalString;
}
static <K, V> List<K> getallKeys(Map<K, V> mapOfWords, V value) {
List<K> keylist = null;
if (mapOfWords.containsValue(value)) {
keylist = new ArrayList<>();
for (Map.Entry<K, V> entry : mapOfWords.entrySet()) {
if (entry.getValue().equals(value)) {
keylist.add(entry.getKey());
}
}
}
return keylist;
}
public static void main(String[] args) {
translatekeyName obj = new translatekeyName();
obj.concatenateString(initialMap(), secondMap());
System.out.println(finalString);
}
}
I want to create a copy of linked hash map and then I want to remove all values (from the List) instead of the first entry. Here is what I got:
LinkedHashMap<String, List<Value>> facetsInCategoriesCopy = new LinkedHashMap<>(facetsInCategories);
if (!facets.equals("something")) {
for (List<Value> value : facetsInCategoriesCopy.values()) {
if (value.size() > 1) {
int nbrOfElements = value.size();
for (int i = nbrOfElements-1; i > 0; i--) {
value.remove(i);
}
}
}
}
After this operation it turns out that facetsInCategories are modified too. Why? And how to solve the issue?
Any help would be appreciated.
I don't have a 50 reputation to add a comment. See this answer Assigning Hashmap to Hashmap
Essentially, the copy constructor you used to make the new map has references to the mutable objects i.e. facetsInCategories and will update that as well when you update the facetsInCategoriesCopy map.
The solution would be to instead do a deep copy instead. I have added test code below, I used String instead of Value
//Test for https://stackoverflow.com/questions/27324315/
public static void testStackO_Q_27324315() {
Map<String, List<String>> facetsInCategories = new LinkedHashMap<String, List<String>>();
String[] values = new String[]{"Test1", "Test2", "Test3"};
List<String> valuesList = new ArrayList<String>(Arrays.asList(values));
facetsInCategories.put("Test", valuesList);
Map temp = Collections.unmodifiableMap(facetsInCategories);
LinkedHashMap<String, List<String>> facetsInCategoriesCopy = (LinkedHashMap<String, List<String>>)deepCopy(temp);
String facets = "test_me";
if (!facets.equals("something")) {
for (List<String> value : facetsInCategoriesCopy.values()) {
if (value.size() > 1) {
int nbrOfElements = value.size();
for (int i = nbrOfElements-1; i > 0; i--) {
value.remove(i);
}
}
}
}
System.out.println(facetsInCategories);
System.out.println(facetsInCategoriesCopy);
}
public static <K1, K2, V> Map<K1, List<V>> deepCopy(
Map<K1, List<V>> original){
Map<K1, List<V>> copy = new LinkedHashMap<K1, List<V>>();
for(Map.Entry<K1, List<V>> entry : original.entrySet()){
copy.put(entry.getKey(), new ArrayList<V>(entry.getValue()));
}
return copy;
}
How to get count the same values from HashMAP?
HashMap<HashMap<String, Float>, String> HM=new HashMap<HashMap<String,Float>, String>();
HashMap<String, Float> h;
h=new HashMap<String, Float>();
h.put("X", 48.0f);
h.put("Y", 80.0f);
HM.put(typeValuesHM, "Red");
h=new HashMap<String, Float>();
h.put("X", 192.0f);
h.put("Y", 80.0f);
HM.put(typeValuesHM, "Red");
h=new HashMap<String, Float>();
h.put("X", 192.0f);
h.put("Y", 320.0f);
HM.put(typeValuesHM, "Blue");
h=new HashMap<String, Float>();
h.put("X", 336.0f);
h.put("Y", 560.0f);
HM.put(typeValuesHM, "Blue");
The values of my HashMap HM are as follows:
{ {x=48,y=80}=Red,{x=192,y=80}=Red,{x=192,y=320}=Blue,{x=336,y=560}=Blue }
Here,
I want to count the similar values in the HashMap HM.
ie) if i give value equals to "Red" means i want to get count=2.
if i give value equals to "Blue" means i want to get count=2.
How to get count the same values from HashMAP HM?
int count = Collections.frequency(new ArrayList<String>(HM.values()), "Red");
Loop through the entry set and drop all values to a second map, the first maps value as a key, the value will be the count:
Map<String, Integer> result = new TreeMap<String, Integer>();
for (Map.Entry<Map<String, Float>> entry:HM.entrySet()) {
String value = entry.getValue();
Integer count = result.get(value);
if (count == null)
result.put(value, new Integer(1));
else
result.put(value, new Integer(count+1));
}
The result map for your example should be like this:
{"Red"=2, "Blue"=2} // values are stored as Integer objects
The only way you can do it is to iterate through all the elements and count the occurrences:
for(String value: hm.values()) {
if (value.equals(valueToCompare)) {
count++;
}
}
int countValue(String toMatch) {
int count = 0;
for (String v : HM.values()) {
if (toMatch.equals(value)) {
count++;
}
}
return count;
}
Also, it is probably overkill to use a HashMap as the key if you are just storing two values. The built in Point uses int, but it would not be hard to re-implement with float.
Iterator<String> iter = HM.values().iterator();
while(iter.hasNext()) {
String color = iter.next();
if(color.equals("Red")) {
} else if(color.equals("Green")) {
} else if(color.equals("Blue")) {
}
}