I have some data that looks like this
myobject{keyone:"valueone",keytwo:"valuetwo",keythree:"valuethree"}
myobject{keyone:"valueone",keytwo:"valuetwo",keythree:"valuethree"}
myobject{keyone:"valueone",keytwo:"valuetwo",keythree:"valuethree"}
And I'm wondering what the best way to create a bunch of objects from it would be. I've written the following regex to extract all the values from a particular Key...
Pattern p_keyone = Pattern.compile("keyone:\"(.+?)\"\\,");
Matcher match_keyone = p_keyone.matcher(string);
while(match_keyone.find()) {
myobjects.add(new MyObject(match_keyone.group(1));
}
Which gives me a bunch of objects with a single argument...
myobjects.add(<valueone>);
Is there a way I can execute a single regex query and create a bunch of objects with all the values as arguments in one go. Like this...
new MyObject( <valueone>, <valuetwo> , <valuethree> );
Thanks
Your approach is not bad.
Few things you could change, though it depends on your requirements whether they make sense:
Create a "Factory" class which takes 1 line of data and creates the object.
Read the data line by line, for each line use the Factory to create it.
Depending on how fancy (and error-prone) you want it to get, you could even read the names of the objects and properties and then use reflection to create instances and set the properties.
String.split() could help:
String line = "myobject{keyone:\"valueone\",keytwo:\"valuetwo\",keythree:\"valuethree\"}"
// ^-----[0]------^ ^--[1]-^ ^--[2]-^ ^--[3]-^ ^--[4]---^ ^--[5]---^ ^[6]
String[] parts = line.split("\"");
MyObject myObject = new MyObject(parts[1], parts[3], parts[5]);
Related
I'm working on an implementation of a database in Java, and need to create an Antlr parser to process query strings like this one:
(category(Chinese) || category(Italian)) && price <= 2
I have implemented a method Set<String> category(String regex) for my database, which returns a set of the names of the restaurants that match the given text, but I have no idea how to call this method from some specific rule in my parser.
I expect that I have to have a parameter in my .g4 file that takes in my Java database object, but using #parser::members{} seems like it's only useful for initialising objects.
Any help would be appreciated!
This is my first post on stackoverflow, so sorry if it's not clear enough
If you want to give the Set to the parser so that it can then be accessed inside it you can do the following:
#parser::members {private Set<String> mySet;
public MyParser(CharStream input, Set<String> theSet) {
this(input);
mySet = theSet;
}
}
You can then access the respective mySet inside any parser-action during parsing. However you need to think about using the correct constructor.
You may also need to put the respective import statements in #parser::header.
I'm using a MultiValueMap from Apache Collections, to collect different types of word (Nouns, Verbs etc) and I want to check that I have at least one of each word type before continuing.
The general outline is like so (after initiating the keys):
MultiValueMap wordMap = new MultiValueMap().decorate(new HashMap(), LinkedList.class);
while (wordMap.notAllEmpty()){
wordMap.put(wordType,word) // eg, Noun, Giraffe
}
But I don't have a method for notAllEmpty(). I tried .values().contains(null) but the empty map doesn't contain null. Likewiese .values().isEmpty() doesn't work as all values are put together.
Is there a succinct way to check for this condition, perhaps with a method from the API?
It sounds like your trying to continue with your loop until there is at least one value per key. This is going to open you to a large possibility of an infinite loop if your data set isn't complete. To get to the point though you need to look at the keys, not the values. If you know how many word types there are than you should probably use the following.
int totalWordTypes = 10;
while (wordMap.keySet().size() < totalWordTypes) {
//...
}
Otherwise you'll need a collection of the word types you are looking for and use something like...
while (!wordMap.keySet().containsAll(wordTypesCollection)) {
//...
}
I have a switch statement that compares a String with set of String where each match calls a different method.
switch(((Operation) expr.getData()).getValue()){
case "+":
return add(expr.getNext());
case "car":
return car(expr.getNext());
case "cdr":
return cdr(expr.getNext());
case "cons":
return cons(expr.getNext(), expr.getNext().getNext());
case "quote":
return quote(expr.getNext());
case "define":
handleDefine(expr.getNext());
break;
default:
return null;
}
However, to me this sounds like something that could be achieved far more elegantly and efficiently using a HashMap that links up to an Operation that contains a Method and the number of parameters so I could each method to a HashMap like:
nameToOperation.put("+", new Operation("+", 1, Driver.class.getMethod("add")));
nameToOperation.put("car", new Operation("car", 1, Driver.class.getMethod("car")));
So there would be N different instances of the Operation class each containing the String, Method and number of parameters
And then I could simply call the method using something similar to this (I understand this isn't how you use invoke):
Operation op = ((Operation) expr.getData())
if(op.getNumPars() == 1)
return(op.getMethod().invoke(expr.getNext()));
else
return(op.getMethod().invoke(expr.getNext(), expr.getNext().getNext()));
However, I still don't fully like this solution as I am losing type safety and it still doesn't look that great. Another example I have seen on stackoverflow that looked quite elegant but I don't fully understand is the first solution of the top answer on: How to call a method stored in a HashMap? (Java)
What does everyone on Stackoverflow think the best solution is?
Edit: Just in case anybody searches this and was wondering about my solution, I made each operation such as Add, Car, Cdr have their own class that implemented Command. I then had to make the majority of my methods static, which I suppose by nature each of them were anyway. This seems way more elegant than the original case statement.
basicaly , the answer recommends to go with Command pattern.
"The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that know how to perform it. And this advantage must be kept. There are implementations of this design pattern in which the invoker is aware of the concrete commands classes. This is wrong making the implementation more tightly coupled. The invoker should be aware only about the abstract command class"
Basicaly your map would be type safety. by declaring
Map <character,Command>
Open to Extendibility
It looks like you are trying to write a Scheme interpreter. In that case you're gonna need a map anyway since you need to store all the user defined values und functions.
When the user writes e.g. (define (add a b) (+ a b)), you store the function in the map using "add" as key.
But your functions should use lists as inputs, i.e. each function has exactly one argument which is a list. In Scheme all expressions are lists by the way. Usually a Scheme interpreter consists of a reader and an evaluator. The reader converts the code into a bunch of nested lists.
So basically "(define (add a b) (+ a b))" could be converted into a list structure similar to this.
List<Object> list = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list2.add("add"); list2.add("a"); list2.add("b");
List<Object> list3 = new ArrayList<Object>();
list3.add("+"); list3.add("a"); list3.add("b");
list.add("define"); list.add(list1); list.add(list2);
Of course your code doesn't actually look like this, instead the lists are constructed by recursive methods parsing the input code.
Those lists don't just contain strings btw., they also contain numbers and boolean values. Nested lists like this are the most simple form of an abstract syntax tree (AST). Since the syntax of Scheme is much simpler than that of most other languages, a very simple list structure is enough to store the parsed code.
The evaluator then processes those lists.
To evaluate a list you first recursively evaluate every element in the list and then apply the first element to the rest of the list. That first element must therefore be a user defined function or a build in command e.g. "define".
I have a bunch of strings with weird names (like this docFileeh934fhry) that contain text like this
System.out.println(docFileeh934fhry);
`.............document: 12345.....
...................
...............`
I want to rename these strings. So that the above string will be String doc12345
How can I do this?
I know how to get this number using Pattern.compile
Let's say I have this number String docNumber = "12345";
Now how can I dynamically create a new string?
I tried
String doc+docNumber = docFileeh934fhry; // no result
You might be able to do this with reflection, but it has to be said that this is a very poor approach.
Your naming of variables should not depend on any external input. Instead, give it a name that describes its contents and go from there.
What do you gain by naming it doc1?
If you are looping trough files all you probably want is a currentDocument. Any other variables (firstDocument, nextDocument, oldDocument, etc) you name according to their function, not their contents.
If you want a way to uniquely identify the correct document, create a class instead
class Document {
int id;
string contents;
}
After storing all these Document objects into a collection (like an ArrayList), you can just retrieve the document you need on basis of that id rather than having to mess around with a bunch of generated variables.
Another point to note: how would you even use this when you have 50 documents? 100? 10.000? This would be impossible to maintain.
If you don't want to create a custom class you can go with the HashMap<Integer, String> route.
This isn't how Java works. If you want to associate an object with a String, then use a Map such as a HashMap<String, String>.
Assign the string to the variable w/ the new name. Note that the new name will have to be have been defined when writing the code, it can't be computed on the fly (if that is what you are driving at).
You can't use + in a variable name. As above, you can't make variable names on the fly.
Here maybe one possible solution,use Hashmap,key is your varname(the way as you wish) and value is your string.
Let's say you have two instances of the same bean type, and you'd like to display a summary of what has changed between the two instances - for example, you have a bean representing a user's settings in your application, and you'd like to be able to display a list of what has changed in the new settings the user is submitting (instance #1) versus what is stored already for the user (instance #2).
Is there a commonly used algorithm or design pattern for a task such as this, perhaps something that can be abstracted and re-used for different types of beans? (I'm having a hard time thinking of a good name for this type of problem to know what to Google on). I've checked commons-beanutils and nothing popped out at me.
If you are talking about comparing values, I would consider using reflection and just comparing them field by field.
Something like this:
Field[] oldFields = oldInstance.class.getDeclaredFields();
Field[] newFields = newInstance.class.getDeclaredFields();
StringBuilder changes = new StringBuilder();
Arrays.sort(oldFields);
Arrays.sort(newFields);
int i = 0;
for(Field f : oldFields)
{
if(!f.equals(newFields[i]))
{
changes.append(f.getName()).append(" has changed.\n");
}
i++;
}
This code hasn't been tested. You might need to get the values in the fields and compare them instead of just comparing fields to each other, but it should work in theory.
The reflection not mantains the order of the Field in next calling: it's safier order the arrays.
/*
*declarations of variables
*/
Arrays.sort(oldFields);//natural order - choice 1
Arrays.sort(newFields, new Ordinator());//custom Comparator - choice 2
/*
*logic of comparations between elements
*/
In choice 2 you can decide the logic of sorting (HOW SORTING THE ELEMENTS) with an inner class Ordinator extending Comparator.
PS the code is a draft
We've done something similar with bean utils and it worked well. Things to consider: Do you drill down into field objects - If a Person contains an Address and the address changes do you say the address changed or that address.postalCode changed(we do)? Do you return a list propety name, old value, new value from the diff (we do)? How do you want to handle dates - if all you care about is date part then your comparison should ignore the time? How do you say which fields to ignore?
This isn't really a copy and paste answer but more of list of things that weren't immediately obvious when we wrote our differ.
As for implementation, we just have a static util method that takes two beans and a list of properties to compare and then returns a map of properties to a Pair containing the old value and the new value. Then each bean has a diff(Object o) method that calls the static util method as needed.
These libraries should help.
https://code.google.com/p/beandiff/ - An annotation based bean diffing library. Apache License 2.0
https://github.com/SQiShER/java-object-diff/ - A bean differ based on Visitor pattern. Apache License 2.0
We had a requirement to generate difference between beans in json format for auditing purpose. We ended up implementing it using beandiff library.
** EDIT **
This looks like a newer option. I have not used it though.
http://beandiff.org/
Hope it helps.
Good answers above.
If your data changes structurally, i.e. whole collections of fields may be relevant or not depending on others, you might want to consider differential execution.
Basically, you have a loop over the fields, and you serialize the current field values at the same time as you deserialize the prior values, comparing them as you go.
If there is a conditional test that makes a block of fields relevant or not, you serialize/deserialize the true-or-false value of the conditional test, and use that to decide whether or not to serialize and/or deserialize the affected fields. And it recurs nicely.
Just a suggestion.
Solution using reflection and standard data structures.
Field[] declaredFields = ClassOne.class.getDeclaredFields();
Field[] declaredFields2 = ClassTwo.class.getDeclaredFields();
ArrayList<String> one = new ArrayList<String>();
ArrayList<String> two = new ArrayList<String>();
for (Field field : declaredFields)
{
one.add(field.getName());
}
for (Field field : declaredFields2)
{
two.add(field.getName());
}
List<String> preone = (List<String>)one.clone();
one.removeAll(two);
two.removeAll(preone);
Collections.sort(one);
Collections.sort(two);
System.out.println("fields only in One : " + one);
System.out.println("fields only in Two : " + two);