Sort JPA relational entity lists - jsf

I'm using PrimeFaces to display information in a DataTable. The data in the datatable is actually a List of entity objects which is generated by OpenJPA. And the entities have relations to other entities. This means that there are Lists inside Lists.
For example, an entity called Authors, which has many Books. The data List<Authors> is listed in the datatable. And in order to sort the List i use Collections.sort() which of course doesn't work when i try to sort on the Authors book title. Because the title field is an instance of the Book class.
How do i go about to sort the Lists when there are relationships like this?
Thanks in advance.

Here is an example of sorting by books title, you need to sort your books list :
public static void main(String args[]) {
List<Author> list = new ArrayList<Author>();
for (int i=0;i<5;i++){
Author a = new Author();
a.setName("author"+i);
List<Book> books = new ArrayList<Book>();
for(int j=0;j<4;j++){
Random r = new Random();
char c = (char) (r.nextInt(26) + 'a');
Book b = new Book();
b.setTitle(c+"title");
books.add(b);
}
a.setBooks(books);
list.add(a);
}
/*
* At this point of time you have Authors list which you want to sort by book title.
* So you can do something like below if you want to do it through Collections.sort
*/
for(Author a : list){
Collections.sort(a.getBooks(), new Comparator<Book>(){
#Override
public int compare(Book o1, Book o2) {
return o1.getTitle().compareToIgnoreCase(o2.getTitle());
}});
}
System.out.println(list);
}
Author and Book used in above example:
import java.util.List;
public class Author {
private List<Book> books;
private String name;
#Override
public String toString() {
return "Author [books=" + books + ", name=" + name + "]";
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Book.java:
public class Book {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public String toString() {
return "Book [title=" + title + "]";
}
}

Related

Using a string to specify an object in Java

I have a Combo Bx (Dropdown box) with an index range of 0-20. If there anyways I can use that index to specify which object I want data from? All of the objects use the same naming convention obj0, obj1, obj2, etc. Basically something like this...
public abstract class Person {
private String name;
private String title;
private String email;
private String job;
public Person(String name, String title, String email, String job){
this.name = name;
this.title = title;
this.email = email;
this.job = job;
}
//Getters and Setters
}
public class main extends javax.swing.JFrame {
...misc code...
private void btn_startActionPerformed(java.awt.event.ActionEvent evt) {
Person obj0 = new Person("Jon Doe",
"Program Coordinator",
"jon.doe#test.com",
"Faculty");
Person obj1 = ...
...
Person obj20 = ...
/*
Onclick it uses the index of the current index in the combobox (dropdown)
to specify which object to get the data from.
*/
private void btn_GetActionPerformed(java.awt.event.ActionEvent evt) {
//Uses the obj naming convention plus the index
string foo = "obj" + toString(combobox_Name.getSelectedIndex());
//Fills the textbox using the above string and the getName method
txtbox_username.setText(ToObject(foo).getName);
}
I have created a basic design of what I think you want:
This code creates 20 objects, adds them to a combobox and uses their predefined name when selected to change a textfield.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
class ObjExample {
String name;
public ObjExample(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
public class Main extends JFrame implements ActionListener {
JComboBox jcb = new JComboBox();
JTextField jtf = new JTextField("Text Field");
public Main() {
setSize(200, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int i = 0; i <= 20; i++) {
jcb.addItem(new ObjExample(Integer.toString(i)));
}
jcb.addActionListener(this);
add(jcb);
add(jtf);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jcb) {
ObjExample obj = (ObjExample) jcb.getSelectedItem();
jtf.setText(obj.toString());
}
}
}

groovy not recognizing java getters/setters through field syntax

I have the following inheritance hierarchy defined in java.
public class BaseModel extends HashMap<String, Object> {
public String getString(String key) {
return (String)this.getOrDefault(key, "EMPTY");
}
}
public class Entity extends BaseModel {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Now in a groovy script I try to do the following:
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
and "id" and "name" are not recognized. The funny thing is they are recognized if I do one of the following:
not inherit Entity from BaseModel
Rather than inherit BaseModel from HashMap, make HashMap a data member of BaseModel
inherit Entity directly from HashMap
At first I thought that groovy is not recognizing the "id" and "name" syntax because of extending HashMap, but #3 above proves that incorrect. I am stumped as to why this is not being recognized at this point. Can someone help me out? It should be easy enough to copy paste this and try it out yourself.
The problem seems to be the setters and getters inside the Entity Class, everything in groovy is public and it creates all the getters and setters methods.
I tested the next code in the groovy console and it worked.
public class BaseModel extends HashMap<String, Object> {
public String getString(String key) {
return (String)this.getOrDefault(key, "EMPTY");
}
}
public class Entity extends BaseModel {
private String id;
private String name;
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id
It prints 101 in the groovyConsole output screen.
When Entity is extending from BaseModel or directly a HashMap, Entity becomes a Map. So, when we say entity.id, Groovy is trying to find an entry in the map whose key is 'id'. As there is no such entry, it prints out null.
public class Entity extends HashMap<String, String> {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id //prints null
But when Entity is not extending from BaseModel anymore, entity.id will be interpreted just as a member of Entity.
public class Entity {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id //prints 101

HashMap<String, Student> searching for instance in Student class

I am working with two helper classes (Student, Helper), as well as a main class.
In the Student class, I have the following constructor:
Student(String iName, String iMajor, int iNumber) {
name = iName;
major = iMajor;
number = iNumber;
}
In the Helper class, I declare a HashMap as follows:
HashMap<String, Student> students = new HashMap<String, Student>();
Now, I have written a few method for adding (put) new students into the HashMap construction, as well as a method for retrieving information about a student based on the name.
//Adding new students
Student s1 = new Student("Alex", "Biology", 19);
Student s2 = new Student("Brian", "Chemistry", 20);
Student s3 = new Student("Tom", "Biology", 20);
//etc...
//Get student from name (key)
public Student getFromKey(String key) {
return students.get(key);
}
I am now looking to write a method that finds all students based on either major or number. For instance, the call:
helper.getStudents("Biology");
Should return all the students studying Biology. I imagine the method looking something like:
public Student getStudents(String searchItem) {
for(Students st : students.values()) {
if(searchItem.equals(??)) {
return st;
//Something like this.
However, I can't seem to figure out how to access these values. All the classes have appropriate getter and setter methods, and the program works fine. Any help is highly appreciated!
Assuming this Map exists:
HashMap<String, Student> students = new HashMap<String, Student>();
The following would work:
public Student getStudents(String searchItem) {
for(Map.Entry<String,Student> entry : students.entrySet()) {
Student student = entry.getValue();
//perform conditional logic here
}
Here is a more complete example in case you need it:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class Student {
private String name;
private String major;
private int number;
public Student(String name, String major, int number) {
super();
this.name = name;
this.major = major;
this.number = number;
}
public static void main(String[] args) {
List<String> names = Arrays.asList("Joe", "Jack", "John","James");
List<String> majors = Arrays.asList("English","Math","Geography");
Map<String,Student> students = new HashMap<String,Student>();
for(int i = 0; i < 100; i++){
Collections.shuffle(names);
Collections.shuffle(majors);
students.put(names.get(0) + String.valueOf(i), new Student(names.get(0), majors.get(0), i));
}
List<Student> mathMajors = getStudents(students, "Math");
for(Student student:mathMajors){
System.out.println(student.name);
System.out.println(student.major);
}
}
public static List<Student> getStudents(Map<String,Student> students, String searchToken){
List<Student> results = new ArrayList<Student>();
for(Entry<String,Student> entry:students.entrySet()){
if(entry.getValue().getMajor().equalsIgnoreCase(searchToken)){
results.add(entry.getValue());
}
}
return results;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getMajor() {
return this.major;
}
public void setMajor(String major) {
this.major = major;
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
}
On Github

Array List in C# without a loop

I like to know how to initialise the array without the loops like for, foreach or any LINQ.
From the following code, need to find under 2m length cars within .Netframework using console application.
{
ArrayList = CarType new ArrayList();
CarType.Add(new CarList("Ford"));
((CarList)CarType[0]).Cars.Add(new Car("Focus", 2));
((CarList)CarType[0]).Cars.Add(new Car("Fiesta", 1));
CarType.Add(new CarList("Peugeout"));
((CarList)CarType[1]).Cars.Add(new Car("206", 1));
((CarList)CarType[1]).Cars.Add(new Car("407", 2));
RemoveLargeCars(CarType);
}
public static ArrayList RemoveLargeCars (ArrayList CarType)
{
//Array List should be here
return CarType;
}
It has got two classes as follows.
class Car
{
public string name;
public float length;
public Car(string newName, float newLength)
{
this.name = newName;
this.length = newLength;
}
}
Class CarList
{
public string CarType;
public ArrayList Pipes;
public CarList(string newCarType)
{
carType = newCarType;
Cars = new ArrayList();
}
}
Can you please let me know how to solve this.
Thanks in advance.
Use the static Adapter method on ArrayList
CarType = ArrayList.Adapter(CarList);
But that probably uses a loop internally, you can't get away from them, but at least this hides them.
Well, first of all you should use the generic list type List<T> instead of ArrayList, that will make the code simpler. (And best practive recommends properties rather than public fields):
class Car {
public string Name { get; set; }
public float Length { get; set; }
public Car(string newName, float newLength) {
Name = newName;
Length = newLength;
}
}
class CarList {
public string CarType { get; set; }
public List<Car> Cars { get; set; }
public CarList(string newCarType, List<Car> newCars) {
CarType = newCarType;
Cars = newCars;
}
public CarList(string newCarType) : this(newCarType, new List<Car>()) {}
}
Now use a List<CarList>:
List<CarList> CarType = new List<CarList>();
CarList ford = new CarList("Ford");
CarType.Add(ford);
ford.Cars.Add(new Car("Focus", 2));
ford.Cars.Add(new Car("Fiesta", 1));
CarList peugeot = new CarList("Peugeout");
CarType.Add(peugeot);
peugeot.Cars.Add(new Car("206", 1));
peugeot.Cars.Add(new Car("407", 2));
List<CarList> smallCars = RemoveLargeCars(CarType);
You can use extension methods to easily filter out cars based on a condition:
public static List<CarList> RemoveLargeCars(List<CarList> CarType) {
return CarType.Select(
t => new CarList(t.CarType, t.Cars.Where(c => c.Length < 2f).ToList()
) .ToList();
}
Note that the method doesn't change the original list, but creates a new list.

Nesting Maps in Java

I want to store many details (like name, email, country) of the particular person using the same key in hashtable or hashmap in java?
hashMap.put(1, "Programmer");
hashMap.put(2, "IDM");
hashMap.put(3,"Admin");
hashMap.put(4,"HR");
In the above example, the 1st argument is a key and 2nd argument is a value, how can i add more values to the same key?
You can achieve what you're talking about using a map in each location of your map, but it's a little messy.
Map<String, Map> people = new HashMap<String, Map>();
HashMap<String, String> person1 = new HashMap<String, String>();
person1.put("name", "Jones");
person1.put("email", "jones#jones.com");
//etc.
people.put("key", person1);
//...
people.get("key").get("name");
It sounds like what you might really want, though, is to define a Person class that has multiple properties:
class Person
{
private String name;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//plus getters and setters for other properties
}
Map<String, Person> people = new HashMap<String, Person>();
person1 = new Person();
person1.setName("Jones");
people.put("key", person1);
//...
people.get("key").getName();
That's the best I can do without any information about why you're trying to store values in this way. Add more detail to your question if this is barking up the wrong tree.
I think what you are asking
let us assume you we want to store String page, int service in the key and an integer in the value.
Create a class PageService with the required variables and define your HashMap as
Hashmap hmap = .....
Inside pageService, what you need to do is override the equals() and hashcode() methods. Since when hashmap is comparing it checks for hashcode and equals.
Generating hashcode and equals is very easy in IDEs. For example in eclipse go to Source -> generate hashcode() and equals()
public class PageService {
private String page;
private int service;
public PageService(String page, int service) {
super();
this.page = page;
this.service = service;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public int getService() {
return service;
}
public void setService(int service) {
this.service = service;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((page == null) ? 0 : page.hashCode());
result = prime * result + service;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PageService other = (PageService) obj;
if (page == null) {
if (other.getPage() != null)
return false;
} else if (!page.equals(other.getPage()))
return false;
if (service != other.getService())
return false;
return true;
}
}
The following class is very generic. You can nest ad infinitum. Obviously you can add additional fields and change the types for the HashMap. Also note that the tabbing in the toString method should be smarter. The print out is flat.
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HierarchicalMap
{
private String key;
private String descriptor;
private Map<String,HierarchicalMap>values=new HashMap<String,HierarchicalMap>();
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public void addToSubMap(String key, HierarchicalMap subMap)
{
values.put(key, subMap);
}
public String getDescriptor()
{
return descriptor;
}
public void setDescriptor(String descriptor)
{
this.descriptor = descriptor;
}
public HierarchicalMap getFromSubMap(String key)
{
return values.get(key);
}
public Map<String,HierarchicalMap> getUnmodifiableSubMap()
{
return Collections.unmodifiableMap(values);
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("HierarchicalMap: ");
sb.append(key);
sb.append(" | ");
sb.append(descriptor);
Iterator<String> itr=values.keySet().iterator();
while(itr.hasNext())
{
String key= itr.next();
HierarchicalMap subMap=this.getFromSubMap(key);
sb.append("\n\t");
sb.append(subMap.toString());
}
return sb.toString();
}

Resources