In Java how to test if a Collection of objects contains an object depending on one of its properties.
For example I would like to test if Collection<myObjects> contains an instance of myObjects which has myObjects.name = "myName".
You will have to iterate and do the comparison.
Consider using a Map.
Map<String,myObjects> myMap = new HashMap<String,myObjects>();
myMap.put(myObject.name,myObject);
You can use apache collections, they provide a bunch of handy features including predicate:
public class MyPredicate implements Predicate {
public boolean evaluate(Object input) {
return (MyObject).name = "myName";
}
}
then you can test your collection using :
CollectionUtils.find(myCollection, new MyPredicate());
This will return the first object matching the predicate or null if none matches it.
If you have control on how the data is collected, you can also have some kind of "reverse index" on that property; The index can be a mapping between name and a set of myObjects with that name. This way, you can efficiently retrieve all items with a given name. You can add more indexes the same way.
Related
ArrayList<ParkingList> Parkings = new ArrayList<ParkingList>();
ArrayList<ParkingList> ParkingsDB = new ArrayList<ParkingList>();
for example, Parkings may contain (a,b,c,d) objects and ParkingsDB may contain (a,b)
how can i find c,d
i tried using this method but it didint work,
ArrayList<ParkingList> temp = new ArrayList<ParkingList>(Parkings);
temp.removeAll(ParkingsDB);
my class definition:
public class ParkingList {
Rectangle R;
String Name;
int level;
String BuildingName;
public ParkingList(String BuildingName,String Name, Rectangle R, int level) {
this.R=R;
this.Name=Name;
this.level=level;
this.BuildingName=BuildingName;
}
}
i just wanna know, was my method that i used above a correct method? maybe i have another problem i need to fix.
my criteria is , two objects are equal only if all of the attributes in one object are the same in another object.
in order to utilise removeAll on a collection of custom types you'll need to provide an implementation of the equals method and if possible also the hashCode method as it is used by certain collections in the collection API.
another solution would be to utilise removeIf and specify the criteria which defines when two or more objects are equal.
e.g.
ArrayList<ParkingList> temp = new ArrayList(Parkings);
temp.removeIf(x -> ParkingsDB.stream()
.anyMatch(e -> e.getName().equals(x.getName())));
in this case, the criteria is when any given object in temp has the same name as any given object in ParkingsDB then it shall be removed from the temp list.
now you'll simply need to decide whether to provide your own implementation of equals and hashCode or utilise the example above; in all cases, you'll need to provide a criteria which defines when two given objects are equal.
This is irrelevant to the problem at hand, but you don't seem to respect the Java naming conventions at all.
variables as well as methods (except constructors which is a special type of a method) should start with a lowercase letter and follow the camelCase naming convention i.e rather than Parkings it should be parkings, rather than Name it should be name etc.
Also, you seem to have freely exposed the state of ParkingList. you should enforce encapsulation here by making all the variables private and only provide getters and setters where necessary.
The easiest way for you, as it was already mentioned - to implement ParkingList.equals() method. For example you can generate it by IDE.
Than your code:
temp.removeAll(ParkingsDB);
will work as you expected. This happens since list implementation basically depends on equals() method for checking elements.
You may also use streams:
ArrayList<ParkingList> temp = Parkings.stream()
.filter(parking -> !ParkingsDB.contains(parking))
.collect(Collectors.toList());
I am trying to remove duplicate data from List with specific attribute of an object.
A better option might be to implement equals and hashCode if the identity and equality for this particular type is based on the values of these fields that you are worried about.
That way you can build a set of these objects, which by definition won't contain duplicate instances.
If that's not possible (for example, if you don't have access to the source of this class), you can use anyMatch with a predicate (only works in Java 8):
return list.stream().anyMatch(element -> element.getField().equals(someValue));
If you care about more fields, you can include them in the predicate as well.
In Java <= 7 you will have to iterate over the values:
boolean contains = false;
Iterator<MyObject> = list.iterator();
while(iterator.hasNext() && !contains) {
contains = iterator.next().getField().equals(someValue);
}
return contains;
Overwrite equals(Object obj) method of your class. Cast obj to yoir class and check your certain filed(s).
Then insert all to a Set. There wont be any duplicates on set collection.
I need to store few data pairs in array. Maybe few dozens. I only need to append, no need to delete, no need to search. Then I will access by index. Each pair is String value and Integer value. Java provides so many way to do this, which is the common practice for something like that? Two arrays? A class in an array?
I know how to do this in JavaScript:
var data = []
data.push(['Some name', 100])
//somewhere else
data.push(['Other name', 200])
but I need a solution for Java
Thank you.
For example you can create Pair class (or use implementations from apache commons) to store two elements in List.
List<Pair<String, Integer>> l = new ArrayList<>();
l.add(new Pair<String, Integer>("Some name", 100));
See Generic pair class and Java Pair<T,N> class implementation to see how you can implement Pair class.
It really depends, but in general I think it is better to create an object and use a list of it:
public class MyObject {
private String myString;
private Integer myInt;
// getters setters
}
And use:
List<MyObject> = new ArrayList<>();
(you can also use Pair instead)
If the strings (or ints) are unique, you can use Map, but it is harder to get the insert index.
Another option is just two lists, one for Strings, one for Integers, and use same index in both lists.
I go by using POJO as suggested above for this as this helps to define getter and setter for all the attributes of POJO, compare the objects by overriding equals and hashCode methods. By using getter and setter you know what is stored in what field and comparison can provide you sorting of objects as per your requirements. So this approach is cleaner and extensible for accommodating new requirements too. Also as you are putting data with sequential key so each instance of Pojo can be put in List (if required in sorted order.
I want to implement a filter method to a list of elements in java, so I can get rid of some elements in the list according to my filter. And, most important, I want to design the interface as simple as possible.
Here's my implementation:
I created a class named EasierList, and in the class, I added a method whose signature and implementation is like below:
public IEasierList<T> filter(ISelection<T> filter) {
List<T> result = new ArrayList<T>();
for(T item : mInternalList) {
if(filter.accept(item)) {
result.add(item);
}
}
mInternalList = result;
return new EasierList<T>(this);
}
As for the ISelection interface, it is quite a easy one:
public boolean accept(T obj);
So, you can tell, the users who use this class need to write some code like this to use the filter:
aEasierList.filter(new ISelection<T>() {
#Override
public boolean accept(T obj) {
// some test
return false;
}
});
And I'm wondering if there is a better way to do this, I mean to make the interface even easier to use?
Thanks in advance!
Two points:
First, you don't have to reinvent the wheel, you can use Guava which already supports filtering and transforming of collections and iterables. Sure, those methods are static, but you can use them for standard List, Collection or Iterable interfaces.
Second, since Java doesn't yet support lambda expressions (planned for Java 8), the verbose anonymous classes are the only way how to implement a function object (if you don't want to create a full blown named class). However, you can help yourself a little by not implementing the anonymous class in-place, but by storing it in a static field:
private static final Predicate<String> startsWithS = new Predicate<String>() {
#Override public boolean apply(String string) {
return string.startsWith("S");
}
}
And then using it like this:
Collection<String> strings = ...
Collection<String> filtered = Collections2.filter(strings, startsWithS);
Edit:
One more important thing should be mentioned: These filter and transform methods do not create a new collection independent on the original. What they create is a "view", which is technically a proxy object that points to the original collection and lazily applies the given Predicate or Function on its elements during iteration, querying etc.
This is sometimes convenient, but you have to remember, that in order to obtain a new collection that is independent (not deeply, of course) on the original one, you need to pass it to a constructor (or a factory) of a new collection.
List<String> filteredList =
new ArrayList<>(Collections2.filter(strings, startsWithS));
By the way, this might be a good occasion to use static import for the filter method to reduce the verbosity a little.
I think this is the best you can do in native Java without resorting to an alternate JVM language (Groovy, Scala) that supports closures.
Commons Collections implements essentially the same pattern - check out docs for CollectionUtils.filter and Predicate. The only downside is it doesn't support generics.
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html
So if you're going that route, you may as well use something that's already written and tested.
C# also has a good solution to this pattern via LINQ and extension methods, which makes something analogous to the above filter method appear like it belongs to the Collection itself.
Say, I have a List students;
Person is defined like the following
class Person {
String id;
String name;
}
After getting the students, is the a qucik way to get a list of ids as used, in the form List ids.
Guava has Lists.transform function available. You pass in the list you want to transform and return elements associated to the list.
List<Person> people = ...;
List<String> ids = Lists.transform(people, new Function<People, String>(){
public String apply(People person){
return person.getId();
}
});
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Lists.html
If you are looking for something like a map function as used in other languages, which build up a new list extracting just the IDs, then no, that's not directly feasible (unless by using some external collection API).
You should go the most straightforward way: iterating on the list and building up a new one by selecting just the IDs.
A way to get these things, like I mentioned, is for example to use a TransformIterator together with a Transformer but these are tools that doesn't come with SDK by default as they reside in Apache Collections (take a look here).
Just like Jack said, Or you can split the id's and make a new sequence out of that and iterate through that.