Say I have
List<SomeObject> objList = new ArrayList<SomeObject>();
If SomeObject contains a field named id. Can we find it through some query like
objList.filter('id=2');
without looping through the list? If not, then why? This can be such a useful method and can be used as an alternative to write a tedious for loop.
Libraries with functional, well, functionality such as functionaljava provide such
methods.
You'd need to use its own List implementation which is incompatible to native Javas (Array)List or convert between the two.
An Example:
import fj.data.Java
import fj.data.List
import fj.F
// Converting an ArrayList
fj.data.List<SomeObject> objList2 = Java.ArrayList_List().f(objList);
fj.data.List<SomeObject> filteredObjList = objList2.filter(new F<SomeObject, Boolean>() {
Boolean f(SomeObject c) { return c.id == 2; }
});
// Converting back to ArrayList
java.util.List<SomeObject> objList2 = Java.List_ArrayList().f(filteredObjList );
By using functionaljava's List through out of your project you would avoid the converting.
Even if this was a supported feature of the language, then it would be Java that would need to do the iterating, so you're back at square one (in terms on time complexity).
What you're looking for is associative mapping. This can be achieved with HashMap. If you want to associate by more than one type of property for example id AND name, then you could make two HashMaps, one whose key is id and one whose key is name.
This of course doesn't scale very well if you want to query for many properties, so the next step would be using an Object oriented database such as Hibernate which will allow you to query the database for objects exactly as in your example.
short: no, you can't
long: you can write own data structure and hash/index fields of object for some more efficient search. but this is not a list, more HashMap or so.
Probably this will help someone,
http://code.google.com/p/joquery/
this library supports following code structure,
Filter<Dto> query = CQ.<Dto>filter(testList)
.where()
.property("id").eq().value(1);
Collection<Dto> filtered = query.list();
If you want something like linq for java, check out quaere
Edit: At this point, quaere looks like it is unmaintained. With Java 7 being EOL, you should be on Java 8 whose Stream API should get you most of the way there when compared to Linq's dot syntax. See this page for some examples.
Here
How do you query object collections in Java (Criteria/SQL-like)?
you can see some nice option/ I've sopped on this one actually.
Related
Time and again, I find myself in the situation where I want to use a value, and add it to a collection at the same time, e.g.:
List<String> names = new ArrayList<>();
person1.setName(addTo(names, "Peter"));
person2.setName(addTo(names, "Karen"));
(Note: using java.util.Collection.add(E) doesn't work of course, because it returns a boolean.)
Sure, it's easy to write a utility method myself like:
public static <E> E addTo(Collection<? super E> coll, E elem) {
coll.add(elem);
return elem;
}
But is there really not something like this already in JavaSE, Commons Collections, Guava, or maybe some other "standard" library?
The following will work if you use Eclipse Collections:
MutableList<String> names = Lists.mutable.empty();
person1.setName(names.with("Peter").getLast());
person2.setName(names.with("Karen").getLast());
The with method returns the collection being added to so you can easily chain adds if you want to. By using getLast after calling with on a MutableList (which extends java.util.List) you get the element you just added.
Note: I am a committer for Eclipse Collections.
This looks like a very strange pattern to me. A line like person1.setName(addTo(names, "Peter")) seems inverted and is very difficult to properly parse:
An existing person object is assigned a name, that name will first be added to a list of names, and the name is "Peter".
Contrast that with (for example) person1.setName("Peter"); names.add(person1.getName());:
Make "Peter" the name of an existing person object, then add that name to a list of names.
I appreciate that it's two statements instead of one, but that's a very low cost relative to the unusual semantics you're proposing. The latter formatting is easier to understand, easier to refactor, and more idiomatic.
I would be willing to wager that many scenarios that might benefit from your addTo() method have other problems and would be better-served by a different refactoring earlier on.
At its core the issue seems to be that you're trying to represent a complex data type (Person) while simultaneously constructing an unrelated list consisting of a particular facet of those objects. A potentially more straightforward (and still fluent) option would be to construct a list of Person objects and then transform that list to extract the values you need. Consider:
List<Person> people = ImmutableList.of(new Person("Peter"), new Person("Karen"));
List<String> names = people.stream().map(Person::getName).collect(toList());
Notice that we no longer need the isolated person1 and person2 variables, and there's now a more direct relationship between people and names. Depending on what you need names for you might be able to avoid constructing the second list at all, e.g. with List.forEach().
If you're not on Java 8 yet you can still use a functional syntax with Guava's functional utilities. The caveat on that page is a worthwhile read too, even in Java-8-land.
In com.google.api.services.admin.directory.model.User, many methods, such as getAddresses() and getPhones(), return a Java object that I can’t figure out what to do with.
Using toString(), I can see that the data I want is in the object (and looks like a list of HashMaps), but I can’t figure out how to convert it to a form that I can access, such as a list or array of UserAddress or UserPhone?
I’d also like to know how to build such objects so I can update users (although I suppose it’s likely that the answer to the first part of my question may make how to build them obvious)?
I have been able to update others things that don’t involve such objects, so I don’t need help with reading and updating in general, but I’ve struggling with these object for a couple of days now and can’t figure it out. Thanks.
The Google Directoy API uses JSON for communication. The Java client library used to communicate with the API parses and serializes the JSON to and from Java objects for easier usage in code. Have a look here for an idea of how it works: https://code.google.com/p/google-http-java-client/wiki/JSON
The problem with the current version of the library is that it doesn't serialize all the fields in the User class to usable objects. Instead maps, or list of maps, are used for complex fields. For example the phones field should be turned into a list of UserPhone objects, but instead becomes a list of maps. The only field that is being properly serialized is the name field, being a UserName object.
One way to manually turn the maps into the correct object is to use a json parser like Gson and parse the maps. Like this:
Gson gson = new GsonBuilder().create();
ArrayList phones = (ArrayList) user.getPhones();
for (Object phone : phones) {
UserPhone userPhone = gson.fromJson(phone.toString(), UserPhone.class);
System.out.println(userPhone.getType() + "=" + userPhone.getValue());
}
I believe those methods return a collection, in which case you'll probably want to access the items they contain via their iterator. Something like this should work:
ListIterator addresses = user.getAddresses().iterator();
while(addresses.hasNext()) {
Address address = addresses.next();
// do something with the address
}
If you're not familiar with the Iterator object, this article might help: How to use Iterator
Thank you, but User.getAddresses() and User.getPhones() do not have iterator methods, so neither of the answers proposed here will work.
"ListIterator addresses = user.getAddresses().iterator();" gets the compiler error “The method iterator() is undefined for the type Object”.
"for (UserAddress addr : user.getAddresses())" gets the compiler error “Can only iterate over an array or an instance of java.lang.Iterable”.
I finally found a way to get the job done, though. The follow codes actually works, even though it's difficult to believe this is the way I'm "supposed to" do it.
ArrayList<ArrayMap<String,String>> phones = (ArrayList<ArrayMap<String,String>>)user.getPhones();
for (ArrayMap<String,String> phone : phones)
System.out.println(phone.get("type") + "=" + phone.get("value"));
It’d be nice to get the data into an instance of UserPhone, but I can’t figure out how to do that (other than doing a get & UserPhone.setXxxx for every possible keyword).
I was able to update a phone number by passing User.setPhones() an ArrayList<UserPhone> that I built from scratch.
I'm looking at the examples giving on this page (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.repositories) about method naming, is it possible to create a complex chain method name such as
findByProgrammeAndDirectorAndProgDateBetweenOrderByProgDateStartTimeAsc
In the example they give, they are only doing an OrderBy on one value. In the example above ProgDate and StartTime would be two separate values.
The trick is to simply delimit the properties you want to sort by using the direction keywords Asc and Desc. So what you probably want in your query method is something like:
…OrderByProgDateAscStartTimeAsc
Note, how we conclude the first property definition by Asc and keep going with the next property.
Generally speaking, we recommend switching to #Query based queries, once method names exceed a certain length or complexity. The main reason being that it's awkward for clients to call these very long methods. With #Query you rather get the full power of the query language plus a reasonably sized method name that might be of higher level language to express the intent of the query.
I am Sharing one other approach code snippet for implementing get operation where performing sort operation ordered by multiple column
List<Order> orders = new ArrayList<Order>();
Order StartTimeOrder = new Order(Sort.Direction.DESC, "StartTime");
orders.add(StartTimeOrder);
Order progDateOrder = new Order(Sort.Direction.ASC, "ProgDate");
orders.add(progDateOrder);
return repository.findAll(Sort.by(orders));
Yes it's should be possible:
Try this:
findByProgrammeAndDirectorAndProgDateBetweenOrderByProgDateStartTimeAsc(String programme, String director, Date progStart, Date progEnd);
I have not tested the code, but according to things I've already done, it should work.
A bit more compact :
return repository.findAll(
Sort.by(List.of(
new Order(Sort.Direction.DESC, "StartTime"),
new Order(Sort.Direction.ASC, "ProgDate")
))
);
or
return repository.findAll(
Sort
.by(Direction.DESC, "StartTime")
.and(Sort.by(Sort.Direction.ASC, "ProgDate"))
);
I have the following question:
if I have the following line of code:
List<Position> allPos = posDBM.getAllPos();
Position is an object
posDBM is a SQLite Database Manager class, which manages the SQLite database,
getAllPos() returns all database data.
The return type of getAllPos() is List<Position>.
If I want to initialize a List<> like this List<Position> pos = new, I have to specify the type of the List (ArrayList, LinkedList, etc.) .
So back to my question, what kind of List do I have, after I filled the list from the database?
I would guess it's an ArrayList , but I can't find any source to back this up. It's just a matter of interest...
You don't have to know; that's the point. The interface is what matters to you, not the implementation.
You can't know without looking at the source of that method. But even if you do, it's immaterial to your client. All you call are List methods.
That you will find in getAllPos() source code. List<Position> due to Polymorphism will accept all classes implementing List interface.
It you are just curious, then one way to find out is to do something like this:
List<Position> allPos = posDBM.getAllPos();
System.out.println("The class is " + allPos.getClass().getName());
Of course, you don't need to know ... because you don't need to instantiate the list implementation class yourself. The database management code deals with that.
The returned List<Position> is a generic or a Strongly Typed list. The option that you were asking is about ArrayList which specifies a list that can take up any object. This will require an overhead of Boxing and Unboxing when writing / reading using the ArrayList.
Ideally you should not worried about the actual implementation , once you have List returned from the method call , you can just iterate over it like this .
List<Position> allPos = posDBM.getAllPos();
for(Position position : allPos){
//Your code goes here
}
And if you want to initialize a new list you can do it in many ways by using different implementations of List interface , now which implementation you want to choose very much depends on your requirement.
I would suggest you to add a breakpoint and see allPos variable after posDBM.getAllPos(), the debugger should tell you the Type.
What is the fastest way to get the selected objects from an array?
MyObject[] objects = new MyObject[]{new MyObject(true), new MyObject(false)};
MyObject[] selectedObjects = ???
Is there a faster way than:
ArrayList<MyObject> selObjectsList = new ArrayList<MyObject>();
for(MyObject obj : objects){
if(obj.isSelected()){
selObjectsList.add(obj);
}
}
selectedObjects = selObjectsList.toArray(new MyObject[0]);
This are many lines for a simple operation, is there a shorter operation to do the same?
With the standard libraries, there is no (fundamentaly) neater way to do it. But there are numerous third-party libraries that have filter or predicate support. Google Collections comes to mind. And I have also heard good things about LambdaJ. Hopefully, things will improve with Java 8!
With LambdaJ it could look something like this:
select(myList, having(on(MyObject.class).isSelected()));
Edit I interpreted "fastest" as shortest number of lines. If it was performance you was thinking of, this answer might not be appropriate.
Unfortunately, no. If you are using an ArrayList, which is a linear list, then your are effectively forcing a linear search.
If you want to improve lookup, then you can use something like a Map that will allow quicker lookups, but you will have to use an intelligent method for setting the keys. For instance, if you were lookup up orders, you might use the order number as the key.
Use a Map.
Map<Boolean, List<MyObject>> someMap;
Then you can do the following to retrieve the List of 'MyObjects' that are selected.
someMap.get(true);
And to populate...
someMap.put(myObjectInstance.isSelected(), myObjectInstance);