Is it possible to make library classes comparable without extending them?
import org.json.JSONObject;
LinkedList<JSONObject> list = getListFromFunction();
TreeSet<JSONObject> treeSet = new TreeSet<JSONObject>(list);
Making a TreeSet here is not possible as JSONObject is not comparable. How can I "attach" a custom comparator to JSONObject? (There is a unique property, say "_some_id" to compare with)
We can use Comparator in such a case and handle the scenario. Please refer the below example.
Main Class
public class ComparatorTest{
public static void main(String[] ar) {
// System.out.println(new Sample().stringTimes("vivek", 5));
JSONObject emp1 = new JSONObject();
JSONObject emp2 = new JSONObject();
try {
emp1.put("department", "IT");
emp1.put("name", "bvivek");
emp1.put("id", 1);
emp2.put("department", "IT");
emp2.put("name", "avikash");
emp2.put("id", 2);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<JSONObject> employess = new ArrayList<JSONObject>();
employess.add(emp1);//add to list
employess.add(emp2);//add to list
System.out.println(employess);//unsorted, as is
Collections.sort(employess, new JSONComparator("name"));
System.out.println(employess);//sorted as per the field
//using treeSet
TreeSet<JSONObject> jsonInTree = new TreeSet<JSONObject>(new JSONComparator("id"));
jsonInTree.addAll(employess);
System.out.println(jsonInTree);//using the tree implementation
}
}
JSONComparator
class JSONComparator implements Comparator<JSONObject> {
private String fieldToCompare;
public JSONComparator(String fieldToCompare) {
this.fieldToCompare = fieldToCompare;
}
#Override
public int compare(JSONObject o1, JSONObject o2) {
String id1 = "";
String id2 = "";
try {
id1 = o1.getString(this.fieldToCompare);
id2 = o2.getString(this.fieldToCompare);
} catch (JSONException e) {
}
return id1.compareTo(id2);
}
}
The simplest way to do something like this will work for any classes that aren't comparable. The way you do this is by creating your own comparing method, you can do this in a way like:
public static int compareJSONObjects(JSONObject obj1, JSONObject obj2){
if(obj1.getField()>obj2.getField()){
return 1;
}else{
return -1;
}
}
now when you call list.sort() you can create your own Comparator like this:
list.sort( (obj1, obj2) -> compareJSONObject(obj1, obj2) );
by doing this you cut down on the amount of lines required, as this entire thing could be shortened to 1 line by using ternary and doing:
list.sort( (obj1, obj2) -> obj1.getField()>obj2.getField() ? 1 : -1 );
Related
Is it possible to convert jsonobject code to a java object just using JDK and without other libraries like Gson or jackson? Trying to convert the code below to work without JSON.
public void run(){
boolean flag = true;
while (flag){
try {
JsonObject jsonObject = Json.createReader(bufferedReader).readObject();
if(jsonObject.containsKey("userID"))
System.out.println("["+jsonObject.getString("userID")+"]: "+jsonObject.getString("message"));
} catch (Exception e) {
flag = false;
interrupt();
}
} //while loop brackets
}
I think I found an answer:
Created a global variable string array
private String[] address;
and then corrected the code. I think this will work, will troubleshoot later.
boolean flag = true;
while (flag){
try {
Object o = new BufferedReader(bfr).readLine(); /** MIGHT BE PROBLEMS HERE **/
if(o.equals(address)) /** From here **/
System.out.println("["+o.toString()+"]: "+o.toString());
/** To here**/
} catch (Exception e) {
flag = false;
interrupt();
}
} //while loop brackets
} // run brackets```
Create a new class with 2 String attributes, then create a new instance with your json object.
public class MyObject() {
private String attribute1;
private String attribute2;
public MyObject(String s1, String s2) {
attribute1 = s1;
attribute2 = s2;
}
}
MyObject myObj = new MyObject(jsonObjec.getString("userID"),jsonObjec.getString("message"));
To use it in a loop simple create an array (or ArrayList) of that type :
ArrayList<MyObject> objects = new ArrayList<>();
In your loop :
objects.add(new MyObject(jsonObjec.getString("userID"),jsonObjec.getString("message")));
I am trying to sort a JsonArray in Java using GSON, I would like to sort everything inside that array via a variable key, meaning there is a string somewhere containing something that is the key that the object needs to be sorted by.
Key Variable: varkey1
[{"varkey1":1,"othervarkey":1},{"varkey1":6,"othervarkey":2},{"varkey1":3,"othervarkey":3},{"varkey1":12,"othervarkey":4},{"varkey1":998,"othervarkey":5}]
So it should go like like:
[{"varkey1":1,"othervarkey":1},{"varkey1":3,"othervarkey":2},{"varkey1":6,"othervarkey":3},{"varkey1":12,"othervarkey":4},{"varkey1":998,"othervarkey":5}]
Well, you could just implement a sorting algorithm that could be specialized for Gson JsonElements.
If not, you could just re-use standard Collections.sort(...) that can merely do the job for you.
For some reason, JsonArray implements Iterable and not List where the latter can be sorted with Collection.sort.
So, a custom JsonArray-to-List is required:
final class JsonArrayList
extends AbstractList<JsonElement> {
private final JsonArray jsonArray;
private JsonArrayList(final JsonArray jsonArray) {
this.jsonArray = jsonArray;
}
static List<JsonElement> of(final JsonArray jsonArray) {
return new JsonArrayList(jsonArray);
}
// This method is required when implementing AbstractList
#Override
public JsonElement get(final int index) {
return jsonArray.get(index);
}
// This method is required when implementing AbstractList as well
#Override
public int size() {
return jsonArray.size();
}
// And this one is required to make the list implementation modifiable
#Override
public JsonElement set(final int index, final JsonElement element) {
return jsonArray.set(index, element);
}
}
Now, the rest is simple:
// No even need of Gson instantiation
final JsonArray jsonArray = new JsonParser()
.parse(jsonReader)
.getAsJsonArray();
// Create a JsonArray to a List view instance
final List<JsonElement> jsonElements = JsonArrays.asList(jsonArray);
// Sorting the jsonElements object
Collections.sort(jsonElements, (e1, e2) -> {
final int i1 = e1.getAsJsonObject().get("varkey1").getAsInt();
final int i2 = e2.getAsJsonObject().get("varkey1").getAsInt();
return Integer.compare(i1, i2);
});
Since the jsonElements is just a view for jsonArray, jsonArray is actually sorted.
Try the following:-
String jsonListString = "[{\"varkey1\":1,\"othervarkey\":1},{\"varkey1\":6,\"othervarkey\":2},{\"varkey1\":3,\"othervarkey\":3},{\"varkey1\":12,\"othervarkey\":4},{\"varkey1\":998,\"othervarkey\":5}]";
JSONArray jsonArray = new JSONArray(jsonListString);
// Create Java ArrayList from JSON Array
ArrayList<JSONObject> array = new ArrayList<JSONObject>();
for (int i = 0; i < jsonArray.length(); i++) {
try {
array.add(jsonArray.getJSONObject(i));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Sort the Java Array List
Collections.sort(array, new Comparator<JSONObject>() {
#Override
public int compare(JSONObject lhs, JSONObject rhs) {
// TODO Auto-generated method stub
try {
return (lhs.getInt("varkey1").compareTo(rhs.getInt("varkey1")));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 0;
}
}
});
// convert Java Array List to JSON Array and then to String representation.
jsonArray = new JSONArray(array);
jsonListString = jsonArray.toString();
This code:-
Creates JSONArray from String.
Creates Java ArrayList from JSONArray.
Sort Java ArrayList using Collections.sort()
Then Create JSONArray from Java ArrayList.
Then return JSONArray as JSON String representation.
This will return the sorted json. Used the gson library.
pass the Args: 1. jsonArray, 2. "othervarkey"
private static JsonArray JsonObjectSort(final JsonArray jsonArray, final String sortBy) {
final JsonArray sortedArray = new JsonArray();
final ArrayList<JsonObject> listJsonObj = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
listJsonObj.add((JsonObject) jsonArray.get(i));
}
Collections.sort(listJsonObj,
(o1, o2) -> o1.get(sortBy).getAsString().compareToIgnoreCase(o2.get(sortBy).getAsString()));
for (int i = 0; i < jsonArray.size(); i++) {
sortedArray.add(listJsonObj.get(i));
}
return sortedArray;
}
I am trying to create a function call using hashmap.
For example,
Hashmap--
"a" -> "b"
"c" -> "d"
Now I should parse this Hashmap and create a function like this-
someFun("{a:#,c:#}",new SomeClass(b),new SomeClass(d));
As you can see, a and c are keys of hashmap(first argument) ; b and d are used to create objects (second argument and so on..)
someFun parameters depend on HashMap size..
I am confused! Because I can loop through the map to get Keys and easily create the first argument.
For the second argument, I can use the value to create Objects.
But now how do I add these together to make the function call as specified?
Any help would be very much appreciated :)
P.S: My question is not about getting values/keys from hashmap,but using them to create a function call something as specified.I am not allowed to change someFun consider it as API call.
Is it something like this, that you need:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;
public class Draft {
public static class SomeClass{
final private String val;
public SomeClass(String val) {
this.val = val;
}
}
public void someFun(String str, SomeClass ... classes) {
System.out.println("someFun" + str + Arrays.toString(classes));
}
public static void main(String[] args) {
HashMap<String, String> keyToParam = new HashMap<>();
keyToParam.put("a", "b");
keyToParam.put("c", "d");
String strArg = null;
SomeClass[] classes = new SomeClass[keyToParam.size()];
int pointer = 0;
for(Entry<String, String> entry: keyToParam.entrySet()) {
strArg += entry.getKey() + ":#";
classes[pointer++] = new SomeClass(entry.getValue());
}
new Draft().someFun(strArg, classes);
}
}
First, you should define function like this:
public void someFun(String str, SomeClass[] someClasses) {
// do something
}
Or this:
public void someFun(String str, SomeClass... someClass) {
// do something
}
The former would be better because it's easy to call it by Java Reflection.
Then go through the hashmap and concentrate all keys to a string someString as the first parameter. While doing the iteration, you put all the values into an array someClasses as the second parameter.
Finally get the method and invoke it by (assume that we use SomeObject someObject to call the function):
Method method = SomeObject.getClass().getMethod("someFun");
method.invoke(someObject, new Object[] {someString, someClasses});
To get the HapsMap Key values
HashMap<Object, Object> hashMap= new HashMap<Object,Object>();
...
Set<Object> keyValueSet=hashMap.keySet();
for ( Object keyValue : keyValueSet) {
//you get the key from keyValue and the corresponding value from hashMap using this
hashMap.get(keyValue);
}
The rest is your logic, you can use the values in any place you want.
Try this way...
try {
Object obj = new Object();// Create a new instance of the class that contain your method.
Method m = obj.getClass().getMethod("methodName", param1.class, param2.class, ..);
// In your case Method m = obj.getClass().getMethod("someFun", String.class,SomeClass.class,SomeClass.class);
m.invoke(obj, "{a:#,c:#}", new SomeClass(b),new SomeClass(d));
}catch (SecurityException e) {
// ...
} catch (NoSuchMethodException e) {
// ...
}catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
Method implementation :
public static void someFun(String name, SomeClass classes ...) {
for (SomeClass cls : classes) {
//Logic here
}
}
Hi in my app i am using to create a JSON string. So i thought of using GSON. I have two function one is to store the arraylist and another is normal object. My problem is the ArrayList part is working fine but when i print the normal object function the arraylist object is added to the json part here is my coding
main class
JsonStructure json = new JsonStructure();
json.messages.add("msg 1");
json.messages.add("msg 2");
json.messages.add("msg 3");
json.asecs.add("asec 1");
json.asecs.add("asec 2");
json.asecs.add("asec 3");
Gson gson = new Gson();
output = gson.toJson(json);
Log.i("gson", output);
List<JsonStructure> Allergylist = new ArrayList<JsonStructure>();
for (int i = 0; i < 5; i++) {
JsonStructure oAllergy_Data = new JsonStructure();
oAllergy_Data.setIdmember("hi");
oAllergy_Data.setIduser("hello");
// Adding register to list
Allergylist.add(oAllergy_Data);
}
Gson newgson = new Gson();
String newoutput = newgson.toJson(Allergylist);
Log.i("gson new", newoutput);
and here is my object class
public class JsonStructure {
String idpeople;
String iduser;
String idmember;
ArrayList<String> messages = new ArrayList<String>();
ArrayList<String> asecs = new ArrayList<String>();
public JsonStructure() {
}
public String getIdpeople() {
return idpeople;
}
public void setIdpeople(String idpeople) {
this.idpeople = idpeople;
}
public String getIduser() {
return iduser;
}
public void setIduser(String iduser) {
this.iduser = iduser;
}
public String getIdmember() {
return idmember;
}
public void setIdmember(String idmember) {
this.idmember = idmember;
}
public ArrayList<String> getMessages() {
return messages;
}
public void setMessages(ArrayList<String> messages) {
this.messages = messages;
}
public ArrayList<String> getAsecs() {
return asecs;
}
public void setAsecs(ArrayList<String> asecs) {
this.asecs = asecs;
}
}
my out put that look like
gson(21917): {"asecs":["asec 1","asec 2","asec 3"],"messages":["msg 1","msg 2","msg 3"]}
gson new(21917): [{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]}]
my out put should look like
gson new(21917): [{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"}]
my question is
1)If the gson will display all the object that declare in the class then why the idpeople is not display only arraylist is displayed to my json
2)Should i need to create a separate object file for the Arraylist or any alter coding for my coding
whatever the JsonStructure will contain, all that will be part of your json. if you dont want to include it in your json remove it from class.
I personally think it is not going to harm anyone if your json will contain any extra field and that field is useful for you.
Creating an new class -
JsonStructure oAllergy_Data = new JsonStructure();
will allow your arraylist to be a part of your json. if you dont want it to include, make it separate from JsonStructure class.
Or As an alternative Json can be created like this -
JSONObject outer = new JSONObject();
try {
// field
outer.put("EMAIL", reqModel.getEmail());
// field
outer.put("PASSWORD", reqModel.getPassword());
} catch (JSONException e) {
//
} catch (Exception e) {
//
}
return outer.toString();
remove this line
ArrayList<String> messages = new ArrayList<String>();
ArrayList<String> asecs = new ArrayList<String>();
Use
ArrayList<String> messages ;
ArrayList<String> asecs;
only
I have a ArrayList with custom objects. I want to search inside this ArrayList for Strings.
The class for the objects look like this:
public class Datapoint implements Serializable {
private String stateBased;
private String name;
private String priority;
private String mainNumber;
private String groupadress;
private String dptID;
public Datapoint(){
}
public String getMainNumber() {
return mainNumber;
}
public void setMainNumber(String mainNumber) {
this.mainNumber = mainNumber;
}
public String getName() {
return name;
}
..and so on
I know how to search for a string in a ArrayList but how to do that in a ArrayList with my custom objects:
ArrayList<String> searchList = new ArrayList<String>();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).contains(search)) {
//Do whatever you want here
}
}
So I want to have a function to search in my ArrayList with for example five objects for all "name" strings.
The easy way is to make a for where you verify if the atrrtibute name of the custom object have the desired string
for(Datapoint d : dataPointList){
if(d.getName() != null && d.getName().contains(search))
//something here
}
I think this helps you.
UPDATE: Using Java 8 Syntax
List<DataPoint> myList = new ArrayList<>();
//Fill up myList with your Data Points
List<DataPoint> dataPointsCalledJohn =
myList
.stream()
.filter(p-> p.getName().equals(("john")))
.collect(Collectors.toList());
If you don't mind using an external libaray - you can use Predicates from the Google Guava library as follows:
class DataPoint {
String name;
String getName() { return name; }
}
Predicate<DataPoint> nameEqualsTo(final String name) {
return new Predicate<DataPoint>() {
public boolean apply(DataPoint dataPoint) {
return dataPoint.getName().equals(name);
}
};
}
public void main(String[] args) throws Exception {
List<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
Collection<DataPoint> dataPointsCalledJohn =
Collections2.filter(myList, nameEqualsTo("john"));
}
try this
ArrayList<Datapoint > searchList = new ArrayList<Datapoint >();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).getName().contains(search)) {
//Do whatever you want here
}
}
Probably something like:
ArrayList<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
//Traversal
for(DataPoint myPoint : myList) {
if(myPoint.getName() != null && myPoint.getName().equals("Michael Hoffmann")) {
//Process data do whatever you want
System.out.println("Found it!");
}
}
For a custom class to work properly in collections you'll have to implement/override the equals() methods of the class. For sorting also override compareTo().
See this article or google about how to implement those methods properly.
contains() method just calls equals() on ArrayList elements, so you can overload your class's equals() based on the name class variable. Return true from equals() if name is equal to the matching String. Hope this helps.
Use Apache CollectionUtils:
CollectionUtils.find(myList, new Predicate() {
public boolean evaluate(Object o) {
return name.equals(((MyClass) o).getName());
}
}
String string;
for (Datapoint d : dataPointList) {
Field[] fields = d.getFields();
for (Field f : fields) {
String value = (String) g.get(d);
if (value.equals(string)) {
//Do your stuff
}
}
}
boolean found;
for(CustomObject obj : ArrayOfCustObj) {
if(obj.getName.equals("Android")) {
found = true;
}
}