-
Notifications
You must be signed in to change notification settings - Fork 3
Collections
Classes included in the package 'collection' provides a set of methods to facilitate the work of well-known classes from the core Java: List, Set, Map, array as well. Search through the collection has always been a problem for developers and simple search enforced on the programmer writing many lines of code (Countless foreach, if-else constructions). Fortunately, class 'Collections' solves this problem. The integral part of this class is 'Criteria' mechanism, which allows for complex query conditions.
Criteria mechanism consist of two main classes: Criteria and Restrictions.
Criteria.newCriteria().add(Restrictions.isNotNull("company.name"))
.add(Restrictions.contains("categoriesOfDrivingLicense", "B","D"))
.add(Restrictions.greaterOrEquals("age", 24))
.add(Restrictions.equals("name", "marry", true));
The Restrictions class allows to:
public static Restriction equals(String field, Object value); // Checks whether object is equals to object passed as second parameter
public static Restriction equals(String field, Object value, boolean ignoreCase); // Checks whether object is equals to object passed as second parameter ignoring case sensitivity (Applies to String class)
public static Restriction notEquals(String field, Object value); // Checks whether object is not equals to object passed as second parameter
public static Restriction notEquals(String field, Object value, boolean ignoreCase); // Checks whether object is not equals to object from second parameter ignoring case sensitivity (Applies to String class)
public static Restriction isNull(String field); // Checks whether object is null
public static Restriction isNotNull(String field); // Checks whether object is not null
public static Restriction greater(String field, Number value); // Check whether object is greater than the number passed as second parameter
public static Restriction less(String field, Number value); // Check whether object is less than the number passed as second parameter
public static Restriction greaterOrEquals(String field, Number value); // Check whether object is greater or equals to the number passed as second parameter
public static Restriction lessOrEquals(String field, Number value); // Check whether object is less or equals to the number passed as second parameter
public static Restriction like(String field, String value); // Checks whether object contains substring passed as second parameter
public static Restriction notLike(String field, String value); // Checks whether object does not contains substring passed as second parameter
public static Restriction contains(String field, Object... values); // Checks whether object (Collection) contains all objects passed as second parameter
public static Restriction containsAny(String field, Object... values); // Checks whether object (Collection) contains any of objects passed as second parameter
public static Restriction notContains(String field, Object... values); // Checks whether object (Collection) does not contain all objects passed as second parameter
public static Restriction notContainsAny(String field, Object... values); // Checks whether object (Collection) does not contain any objects passed as second parameter
public static <T> Collection<T> filter(Collection<T> collection, Criteria criteria)
This method allows user to filter collection passed as first argument by specified criteria.
private List<Person> prepareListOfPeople() {
List<Person> people = new ArrayList<Person>();
people.add(new Person("John", "Wolf", 27, null, null));
people.add(new Person("John", "Sky", 31, new Company("Jsolve", new Address("street1", "city1")), prepareListOfCategories("B")));
people.add(new Person("Marry", "Duke", 45, new Company("Sweetener", new Address("street2", null)), prepareListOfCategories("A", "B")));
people.add(new Person("Peter", "Hunt", 41, null, prepareListOfCategories("B", "D")));
return people;
}
Collection<Person> filteredList = Collections.filter(people, Criteria.newCriteria()
.add(Restrictions.isNotNull("company"))
.add(Restrictions.containsAny("categoriesOfDrivingLicense", "A", "D")));
// As a result will be returned collection containing: Marry Duke
Collection<Person> filteredList = Collections.filter(people, Criteria.newCriteria()
.add(Restrictions.greaterOrEquals("age", 31)));
// As a result will be returned collection containing: John Sky, Peter Hunt, Marry Duke
Collection<Person> filteredList = Collections.filter(people, Criteria.newCriteria()
.add(Restrictions.like("company.address.street", "street")));
// As a result will be returned collection containing: John Sky, Marry Duke
truncate allows developer to getting piece of the collection. This method is available in two versions:
public static <T extends Collection<?>> T truncate(T collection, int to);
public static <T extends Collection<?>> T truncate(T collection, int to, int from);
Parameters
- from - the beginning index, inclusive.
- to - the ending index, exclusive.
Every developer knows that the pagination should be done on the database side. Unfortunately, there are situations when we get the whole list, and manually have to split it into pages.
To speed up work on pagination, the paginate method has been created.
Lets say we have a list of the letters of the alphabet:
List<String> alphabet = new ArrayList<>();
alphabet.add("A");
alphabet.add("B");
alphabet.add("C");
alphabet.add("D");
alphabet.add("E");
alphabet.add("F");
alphabet.add("G");
alphabet.add("H");
alphabet.add("I");
...
If you want to display only the four elements, you should use:
Pagination<String> firstPage= Collections.paginate(alphabet, 0, 4);
List<String> lettersOfTheFirstPage = firstPage.getgetElementsOfPage();
// As the result will be returned: A, B, C, D
Pagination<String> secondPage= Collections.paginate(alphabet, 1, 4);
List<String> lettersOfTheSecondPage = secondPage.getgetElementsOfPage();
// As the result will be returned: E, F, G, H
Pagination object has the following construction:
public class Pagination<T> {
private final int page;
private final int resultsPerPage;
private final int totalElements;
private final int numberOfPages;
private final Collection<T> elementsOfPage;
// getters and setters
}
Easy and enjoyable, right?
Method chop is very similar to paginate, but you don't have to invoke it for each page. The signature of this method is the following:
public static <T> ChoppedElements<T> chopElements(Collection<T> collection, int resultsPerPage);
ChoppedElement object has the following construction:
public class ChoppedElements<T> {
private int page;
private final int resultsPerPage;
private final int totalElements;
private final int numberOfPages;
private final List<Collection<T>> listOfPages;
public boolean hasNextPage();
public void nextPage();
public boolean hasPreviousPage();
public void previousPage();
public Collection<T> getElementsOfPage();
public int getPage();
public void setPage(int page);
public int getResultsPerPage();
public int getTotalElements();
public int getNumberOfPages();
public List<Collection<T>> getListOfPages();
The use of this method is as simple as using the paginate method. All what you have to do is specify the collection and the number of items per page:
ChoppedElements<String> choppedElements = Collections.chopElements(alphabet, 4);
List<String> firstPage = choppedElements.getElementsOfPage(); // A, B, C, D
choppedElements.hasNextPage(); // true
choppedElements.nextPage();
choppedElements.getPage(); // 1
List<String> secondPage = choppedElements.getElementsOfPage(); // E, F, G, H
choppedElements.setPage(0);
List<String> onceAgainFirstPage = choppedElements.getElementsOfPage(); // A, B, C, D
etc...
Imagine that you have a huge list of students. In your application you don't want to display all at once, but instead, you want to group them according to the department, field of study, and the semester. Assuming that the list contains the following objects:
public class Student extends Person {
private int semester;
private FieldOfStudy fieldOfStudy;
private Department department;
// getters and setters
}
public class Person {
private String firstName;
private String lastName;
private int age;
private Address address;
// getters and setters
}you can do it in an extremely simple way!
// Example list of students
List<Student> students = new ArrayList<>();
students.add(new Student("John", "Deep", 3, FieldOfStudy.MATHS, Department.AEI));
students.add(new Student("Marry", "Duke", 3, FieldOfStudy.BIOINFORMATICS, Department.AEI));
students.add(new Student("John", "Knee", 3, FieldOfStudy.BIOINFORMATICS, Department.AEI));
students.add(new Student("Peter", "Hunt", 5, FieldOfStudy.BIOINFORMATICS, Department.MT));
students.add(new Student("Lucas", "Sky", 7, FieldOfStudy.COMPUTER_SCIENCE, Department.AEI));
Map<GroupKey, List<Student>> groups = Collections.group(students, "semester", "fieldOfStudy", "department");
In the above example the following groups were created:
- Semester: 3, FieldOfStudy: Maths, Department: AEI = > John Deep
- Semester: 3, FieldOfStudy: Bioinformatics, Department: AEI => Marry Duke, John Knee
- Semester: 5, FieldOfStudy: Maths, Department: MT => Peter Hunt
- Semester: 7, FieldOfStudy: Computer science, Department: AEI => Lucas Sky
Don't always search for duplicates means search for items with the same references. From time to time, for example, we want to find elements with the same identifiers. How do it do fast? Probably two nested loops with 'if construction' inside. What if we distinguish duplicate items by more than one argument? For this reason we have created the duplicates method. The signature is the following:
public static <E> Map<GroupKey, List<E>> duplicates(Collection<E> collection, String ... properties);
Suppose that we have a product object:
public class Product {
private String producer;
private String productName;
private double price;
}All products must have a unique pair: producer and product name. So these two fields will help us to find duplicate products:
Map<GroupKey, List<Product>> duplicates = Collections.duplicates(products, "producer", "productName");
By invoking the uniques will be returned only unique values. So, it is the opposite method to the duplicates.
Example usage:
List<Product> uniques = Collections.uniques(products, "producer", "productName");