I have a for loop from a JSONarray and I add the values to a LinkedHashMap. I would like to avoid adding identical values. I don't know how to do this.
for (int l = 0; l <stops_summaries2.length(); l++){
JSONObject stopObject2 = stops_summaries2.getJSONObject(l);
String stopid2 = stopObject2.getString("id");
System.out.println("stopid2 --->" + stopid2);
String stopurl2 = stopObject2.getString("url");
System.out.println("stopurl2 --->" + stopurl2);
String stopname2 = stopObject2.getString("name");
System.out.println("stopname2 --->" + stopname2);
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
map.put(TAG_NAME, stopname2);
map.put(TAG_SHORT, id);
map.put(TAG_COLOR, stopid2);
itemList.add(map);
}
You can use the functions containsKey(key) and containsValue(values) to check if the map contains a certain key or value.
Edit: I see now that you are creating a new Map on each iteration, is that really what you want to do? That map will not be available outside of the for loop. I think you need to declare the Map before the for loop and then add to it.
Edit: corrected a mistake in my answer,
In my opinion you should avoid to create a different map at each iteration and use it like a container for your data. You could have a wrapper class:
public class Item {
String name;
String id;
String url;
public Item(String nane, String id, String url) {
this.name = name;
this.id = id;
this.url = url;
}
#Override
public boolean equals(Object other){
if (!(other instanceof Item)) return false;
return id.equals( ((Item)other).id);
}
}
and override equals to check if two objects are equals.
Related
I have a Java list of objects which each one contains a String value (code). Also I have a Java Map. I want to check whether all the elements in the Map keys are included in the list of the String values.
The Model class :
public class Obj {
private String code;
private String name;
private String uom;
public Obj(String code, String name, String uom) {
this.code = code;
this.name = name;
this.uom = uom;
}
}
the implemention :
private static final Obj weight = new Obj("weight", "Weight", "Kg");
private static final Obj height = new Obj("height", "Height", "cm");
public static final List<Obj> objMasters = List.of(weight, height);
Set<String> keySet = map.keySet(); // returns the keyset values from the Map
boolean match =objMasters.stream()
.anyMatch(objMaster -> objMaster.getCode().matches(keySet.toString()));
But with this implementation I always get false as the value for the match. What has gone wrong here?
From what I now understood about your question, try this.
List<String> codes = objMasters.stream().map(obj -> obj.getCode()).collect(Collectors.toList());
boolean match = codes.containsAll(keySet);
0,when you use collection or map,please override equals and hashCode methods
/n1,you can deep study of source code like get() contain() and others methods
/n2, by then you will undunderstand why
I have a method that puts value in HashMap of type HashMap<String, Object[]> & returns the same HashMap.
Code for putting value in HashMap:
doc = Jsoup.connect(url).get();
for( org.jsoup.nodes.Element element : doc.getAllElements() )
{
for( Attribute attribute : element.attributes() )
{
String option_ID=element.tagName()+"_"+attribute.getKey()+"_"+attribute.getValue();
String HTMLText=element.text();
int HTMLTextSize=HTMLText.length();
if(!HTMLText.isEmpty())
data.put("Test"+i,new Object[{"Test"+i,option_ID,HTMLText,HTMLTextSize});//adding value in HashMap.
i++;
}
}
I tried iterating as below, which I think is not the correct way :
HashMap<String, Object[]>set=HTMLDocument.createHTMLSet("URL of website");
Iterator it = set.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
As I am getting output as :
Test79 = [Ljava.lang.Object;#14e1a0f
Test378 = [Ljava.lang.Object;#1a5f880
How should I iterate over this HashMap to get Object[] values such as option_ID, HTMLText?
Since each object has toString() method, the default displays the class name representation, then adding # sign and then the hashcode, that's why you're getting the output
[Ljava.lang.Object;#14e1a0f
that means the array contains a class or interface.
One solution would be looping on the array and print each part (or using Arrays.toString method), but I highly recommend you wrapping this to your own class and override the toString method.
The following code might help. Its always better to create a bean class consisting of the necessary information to be stored in an array of objects.
package stack.overflow;
import java.util.HashMap;
import java.util.Map;
public class RetrieveMap {
public static void main(String[] args) {
Person p = new Person();
p.setName("John");
p.setEmpNo("1223");
p.setAge("34");
Person p1 = new Person();
p1.setName("Paul");
p1.setEmpNo("1224");
p1.setAge("35");
Person[] arr = new Person[2];
arr[0] = p ;
arr[1] = p1;
HashMap<String,Person[]> map = new HashMap<String,Person[]>();
map.put("a1", arr);
for(Map.Entry<String, Person[]> entry : map.entrySet()) {
System.out.println("Key:" +entry.getKey());
System.out.println("Value:" +entry.getValue());
for(int i=0;i<entry.getValue().length;i++) {
System.out.println("------------------");
System.out.println("Array:"+i);
Person r1 = (Person)entry.getValue()[i];
System.out.println("Name:" +r1.getName());
System.out.println("Age:" + r1.getAge());
System.out.println("Emp no:" + r1.getEmpNo());
System.out.println("------------------");
}
}
}
}
package stack.overflow;
public class Person {
String name;
String age;
String empNo;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
}
The short answer is your code is behaving exactly correctly; when you call .toString() on an Object[] (which happens implicitly with System.out.println()) you get that odd [<TYPE>#<IDENTIFIER> string. To print the contents of an array, use Arrays.toString().
There are a number of things we can clean up with this code, though.
Avoid mixing generics and arrays (Effective Java Item 25); arrays lack the type safety generics provide, and there's rarely a good reason to use them in modern generic code. A better type signature would be HashMap<String, List<Object>>. This is effectively identical, but in practice much easier to work with.
Don't use arrays to store different types. You appear to be storing a "Test" string, a identifier string, the element's text, and the text's length as fields in an array. This is what objects are for. Define an object with those four fields, and pass them into the constructor. Even better, since everything but i is computable from the element, just pass the element into the constructor and compute the information you need (HTML string, length, etc.) in the constructor or even in the class' getters.
Don't use raw types (Effective Java Item 23) for Iterators and Map.Entrys. Your IDE can warn you when you use raw types so you avoid this common programming error. In your code you should use Iterator<Entry<String, Object[]>> and Entry<String, Object[]>
Don't use Iterator to loop over a Map's elements, use a for-each loop:
for (Entry<String, ...> e : map.entrySet()) {
...
}
Don't call a Map variable a set; they're different things. Similarly a Map.Entry is not a pair - it specifically represents a key-value relationship.
Here's a cleaned-up version of your code, assuming a Container object exists that takes an Element and extracts the data you need.
doc = Jsoup.connect(url).get();
for (org.jsoup.nodes.Element element : doc.getAllElements()) {
for (Attribute attribute : element.attributes()) {
Container c = new Container(i++, attribute);
data.put(c.getKey(), c);
}
}
And:
HashMap<String, Container> map = HTMLDocument.createHTMLMap("URL of website");
for (Entry<String, Container> e : map.entrySet()) {
System.out.println(e.getKey() + " = " + e.getValue());
}
The value is array of Object. Try following instead
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue()[0].toString());
}
I need sort ArrayList of HashMap, this is my code:
ArrayList<HashMap<String,String>> fiduList = new ArrayList<HashMap<String,String>>();
for (MapPoint aList: MapPointsList) {
HashMap<String, String> fidu = new HashMap<String, String>();
fidu.put(KEY_NAME, aList.getRealname());
fidu.put(KEY_TYPE, aList.getType());
fiduList.add(fidu);
}
getRealname get a string like this: AABB/CCCC/DDDD. For example:
AA11/4352/G435;
AA23/0234/J543;
AA02/0032/K123;
I need sort ArrayList comparing first DDDD, CCCC and then BB.
With my code I can sort only all string:
Collections.sort(fiduList, new Comparator<HashMap<String,String>>(){
public int compare(HashMap<String,String> mapping1,HashMap<String,String> mapping2){
return mapping1.get(KEY_NAME).compareTo(mapping2.get(KEY_NAME));
}
});
How can I solve the problem? (I'm new Java user).
Thank
I would suggest another approach. It seems that you use the map for holding two properties of an object - a name and a type. If so, a map is not the appropriate data structure.
You really should create an own class for it:
public final class Fidu {
private final String name;
private final String type;
public Fidu(String name, String type) {
this.name = name;
this.type = type;
}
}
When continuing to analyze the requirements, it seems as if the name consists of three parts, which must be parsed from a delimited string. Thus, your class should reflect that (note the private constructor and the factory method):
public final class Fidu {
private final String namePart1;
private final String namePart2;
private final String namePart3;
private final String type;
private Fidu(String namePart1, String namePart2, String namePart3, String type) {
this.namePart1 = namePart1;
this.namePart2 = namePart2;
this.namePart3 = namePart3;
this.type = type;
}
public static Fidu parse(String name, String type) {
String[] parts = name.split("/");
if (parts.length != 3)
throw new IllegalArgumentException(name);
return new Fidu(parts[0], parts[1], parts[2], type);
}
}
And finally, you should consider a natural ordering on the objects of type Fidu:
public final class Fidu implements Comparable<Fidu> {
...
public int compareTo(Fidu other) {
// an example:
int compare = this.namePart3.compareTo(other.namePart3);
if (compare != 0)
return compare;
compare = this.namePart2.compareTo(other.namePart2);
if (compare != 0)
return compare;
return this.namePart1.compareTo(other.namePart1);
}
}
Additionally this class obviously should also provide an implementation for hashCode and equals. Up to you ...
With that approach you do not need an ArrayList<HashMap<String, String>> anymore, but simply use a List<Fidu> (by the way, for the variable's types always use the interface and not an implementation). This list can then easily be sorted with
List<Fidu> fiduList = ...
Collections.sort(fiduList);
Change your sort from:
return mapping1.get(KEY_NAME).compareTo(mapping2.get(KEY_NAME));
To this:
String[] leftStrings = mapping1.get(KEY_NAME).split("/");
String[] rightStrings = mapping2.get(KEY_NAME).split("/");
int comp = 0;
for (int i = leftStrings.length - 1; i >=0; i--) {
comp = leftStrings[i].compareTo(rightStrings[i]);
if (comp != 0) {
break;
}
}
return comp;
This breaks your string into the three parts, then sorts the strings alphabetically working backwards. The first time we see a mismatch, we report the sort order.
In your Comparator#compare method you can use the class java.util.regex.Pattern to split up the real name using regular expressions:
Pattern pattern = Pattern.compile("(\\w{2})(\\w{2})/(\\w{4})/(\\w{4})");
Matcher matcher = pattern.matcher(realName);
if (matcher.matches()) {
String aa = matcher.group(1);
String bb = matcher.group(2);
String cccc = matcher.group(3);
String dddd = matcher.group(4);
// TODO: compare
} else {
// TODO: real name does not match pattern
}
Notes:
You need to compile the pattern only once (first line); it can then be reused. E.g put it into a static or non-static member variable.
\\w matches the following characters: 'a'-'z', 'A'-'Z', '0'-'9', '_'. If that's not sufficient, use other charachter classes or directly specify a custom character class like [A-Z0-9]
Extend TreeMap create your own map class, In this class provide your way to sort the Map objects, for your string comparisons you can pass the Comparator with your custom logic to TreeMap class.
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
This way all the functionality of the Map will be available to you and you can also implement your own logic of sorting.
I am using a HashMap where the key is String and Value is an object (Signal). While iterating over the Map Can I edit one of the attributes of my object before I write it to a file.
Here is my code
public void createFile(HashMap<String , Signal> map, final BufferedWriter buffwriter, long totalSize) {
final Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()) {
String messageName = iterator.next();
Signal signal = map.get(messageName);
signal.setBandwidth((signal.getSize()/totalSize)*100);
csvOutput.write(signal.getSource());
csvOutput.write(signal.getName());
csvOutput.write(signal.getComponent());
csvOutput.write(Integer.toString(signal.getOccurance()));
csvOutput.write(Integer.toString(signal.getSize()) );
csvOutput.write(Float.toString(signal.getBandwidth()));
csvOutput.endRecord();
}
}
Signal.java
public class Signal implements Comparable<Signal>{
String name;
float bandwidth;
public void setName(String name){
this.name = name;
}
public void setBandwidth(float bandwidth){
this.bandwidth = bandwidth;
}
public String getName(){
return this.name;
}
public float getBandwidth(){
return this.bandwidth;
}
#Override
public int compareTo(Signal signal) {
return 1;
}
In the above piece of code I use messagName as key for each key in the map I get its value
Try to set the bandwidth attribute and then write it to file, but it is not updating the bandwidth.
How can I do it ? Is the only option I am left with to remove the Entry and add another with new value while iterating ?
Thanks In Advance
Let me guess, your bandwidth stays 0? That's because of the way you calculate it. I assume that getSize() returns an int/long, and totalSize is an int/long. This results in the result of your calculation
(signal.getSize()/totalSize)*100
being an int as well. Try the following:
(signal.getSize() / (float) totalSize) * 100
Now one of the operands is a float, what makes the result of the calculation a float as well. Hope this resolves your problem.
See also here.
OK, firstly you CAN modify any object state by reference, so, you got reference to Signal and you can set what do you want (if that object mutable), that one of the reason why I asked to provide code of the class.
I tested your example like next
Signal signal = new Signal();
signal.setName("1");
signal.setBandwidth(23);
HashMap<String , Signal> map = new HashMap<String , Signal>();
map.put("1", signal);
final Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()) {
String messageName = iterator.next();
signal = map.get(messageName);
signal.setBandwidth(1000);
System.out.println(signal.getBandwidth());
}
}
and in result I will see 1000.0
BTW try to use EntrySet insted of keySet + get
Hi guys i've never written a comparator b4 and im having a real problem. I've created a hashtable.
Hashtable <String, Objects> ht;
Could someone show how you'd write a comparator for a Hashtable? the examples i've seen overide equals and everything but i simply dont have a clue. The code below is not mine but an example i found, the key thing in hashtables means i cant do it like this i guess.
public class Comparator implements Comparable<Name> {
private final String firstName, lastName;
public void Name(String firstName, String lastName) {
if (firstName == null || lastName == null)
throw new NullPointerException();
this.firstName = firstName;
this.lastName = lastName;
}
public String firstName() { return firstName; }
public String lastName() { return lastName; }
public boolean equals(Object o) {
if (!(o instanceof Name))
return false;
Name n = (Name)o;
return n.firstName.equals(firstName) &&
n.lastName.equals(lastName);
}
public int hashCode() {
return 31*firstName.hashCode() + lastName.hashCode();
}
public String toString() {
return firstName + " " + lastName;
}
public int compareTo(Name n) {
int lastCmp = lastName.compareTo(n.lastName);
return (lastCmp != 0 ? lastCmp :
firstName.compareTo(n.firstName));
}
}
A Comparator will tell you which of two items is larger. If this has meaning for your HashTable, only you can say what the meaning is. It would be very unusual to want to compare two HashTables in this way.
That's not a Comparator class. That's a Name class that implements Comparable.
Hashtable and Hashmap don't use either Comparator or Comparable. If you want sorted keys use a TreeMap.
Comparators are used to sort a list. A Hashtable (note the case) is not ordered by its elements. You can order a table by iterating over its keys (in the case you'd want to order on its keys, I presume) and put them in a List. The next thing to do is to sort the List and iterate over the List, and use a get out of the Hashtable to get its associated value.
Here is an example (using HashMap, since it's more integrated with the rest of the Java Collections. A HashMap is essentially the same as Hashtable.):
public static void main(String... arg) {
HashMap<String, Object> x = new HashMap<String, Object>();
x.put("second", " ordered!");
x.put("first", "Correctly");
LinkedList<String> keys = new LinkedList<String>();
for(final String f : x.keySet()) {
keys.add(f);
}
Collections.sort(keys, new Comparator<String>() {
public int compare(String first, String second) {
// return -1 is "first < second"
// return 1 is "first > second"
// return 0 is "first == second"
return first.compareTo(second);
}
});
for(final String f : keys) {
System.out.print(x.get(f));
}
System.out.println();
}
The order of the list keys is sorted by the anonymous Comparator class. It will sort alphabetically, as is the default for Strings. You can use your own key object, like you mentioned. If you don't implement Comparator in this key object, then you can supply, as in the above example. Else you can use the default Comparator by calling:
Collections.sort(keys);
Which will use the classes implementation of Comparator. If it does not implement Comparator, then it will throw an exception (since it will cast to a Comparator)