i'm writing a function to create xls sheets from JFXTableView.
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("user details");
XSSFRow header = sheet.createRow(0);
String arrayOfHeaders [] = {"Sr. No.","Name of the Member", "Customized workout card status","Contact No.","Current programme taken","Current package taken",
"Purpose of taking customized workout card", "body type identified"," Current Body weight","Current height","payment amount",
"Mode of payment"};
for(int i=0; i<arrayOfHeaders.length; i++){
header.createCell(i).setCellValue(arrayOfHeaders[i]);
}
int index=1;
for(Member item: tableView.getItems()){
XSSFRow row = sheet.createRow(index);
int cellIndex=0;
for (Method m : item.getClass().getMethods()) {
// The getter should start with "get"
// I ignore getClass() method because it never returns null
if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
row.createCell(cellIndex).setCellValue((String) m.invoke(item));
}
cellIndex++;
}
index++;
}
With the above code, i'm able to retrieve values from the table through the getters, but the problems is item.getClass().getMethods() returns getters in a random order and that is not acceptable as i want the values according to the headers as defined.
I have many such tables, each with their own Class and getters, and writing different functions for each one of them seems too lengthy. So, what i'm planning to do is write a function where i could pass on the getters of each different table object in an array, so it could loop through all the getters of the particular tableView object. Something like this:
createSheets(arrayOfHeaders, tableView.getItems(), arrayOfGetters);
The example of one such Member Class being used by my current tableView is:
public static class Member{
private final SimpleStringProperty name;
private final SimpleStringProperty status;
private final SimpleStringProperty contact;
private final SimpleStringProperty programme;
private final SimpleStringProperty packages;
private final SimpleStringProperty purpose;
private final SimpleStringProperty bodyType;
private final SimpleStringProperty weight;
private final SimpleStringProperty height;
private final SimpleIntegerProperty paymentAmount;
private final SimpleStringProperty paymentMode;
public Member (String name, String status, String contact, String programme, String packages, String purpose,
String bodyType, String weight, String height, int paymentAmount, String paymentMode){
this.name = new SimpleStringProperty(name);
this.status = new SimpleStringProperty(status);
this.contact = new SimpleStringProperty(contact);
this.programme = new SimpleStringProperty(programme);
this.packages = new SimpleStringProperty(packages);
this.purpose = new SimpleStringProperty(purpose);
this.bodyType = new SimpleStringProperty(bodyType);
this.weight = new SimpleStringProperty(weight);
this.height = new SimpleStringProperty(height);
this.paymentAmount = new SimpleIntegerProperty(paymentAmount);
this.paymentMode = new SimpleStringProperty(paymentMode);
}
public String getName() {
return name.get();
}
public String getStatus() {
return status.get();
}
public String getContact() {
return contact.get();
}
public String getProgramme() {
return programme.get();
}
public String getPackages() {
return packages.get();
}
public String getPurpose() {
return purpose.get();
}
public String getBodyType() {
return bodyType.get();
}
public String getWeight() {
return weight.get();
}
public String getHeight() {
return height.get();
}
public int getPaymentAmount() {
return paymentAmount.get();
}
public String getPaymentMode() {
return paymentMode.get();
}
}
Related
I am trying to use BiConsumer to accept an object that contains variables, an object and a list of strings in Java. I am not sure how to set the values into one object if using just BiConsumer. Maybe, if I tried to wrap Student object in a List and pass it into a new Student might help, but so far I get a null object. I haven't seen a lot of post with object containing just variables in one object and using BiConsumer.
#Test
public void testStudent() {
List<Object> objectList1 = new ArrayList<>();
Student student = new Student();
StudentLevel studentLevel = new StudentLevel("freshman", true);
List<String> studentLists = Arrays.asList("Maria", "Jose", "Juan");
Student student1 = new Student("Maria", "Lopez", "A", studentLevel, studentLists);
objectList1.add(student1);
BiConsumer<Object, List<Object>> biconsumer = (obj, list) -> {
for (Object object: list) {
// set and get but how?
// obj = object;
}
};
// To accept values from the object list see below for desired output
biconsumer.accept(student, objectList1);
// For debugging purpose
System.out.println("All Student: " + student);
}
public class Student {
private String name;
private String lastName;
private String grade;
private StudentLevel studentGrade;
private List<String> studentList;
public Student(final String name, final String lastName, final String grade, final StudentLevel studentGrade, final List<String> studentList) {
this.name = name;
this.lastName = lastName;
this.grade = grade;
this.studentGrade = studentGrade;
this.studentList = studentList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public StudentLevel getStudentGrade() {
return studentGrade;
}
public void setStudentGrade(StudentLevel studentGrade) {
this.studentGrade = studentGrade;
}
public List<String> getStudentList() {
return studentList;
}
public void setStudentList(List<String> studentList) {
this.studentList = studentList;
}
}
public class StudentLevel {
private String level;
private Boolean pass;
public StudentLevel(final String level, final Boolean pass){
this.level = level;
this.pass = pass;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public Boolean getPass() {
return pass;
}
public void setPass(Boolean pass) {
this.pass = pass;
}
}
Desired output:
student = {Student#887}
name = "Maria"
lastName = "Lopez"
grade = "A"
studentGrade = {StudentLevel#889}
level = "freshman"
pass = {Boolean#906} true
studentList = {Arrays$ArrayList#890} size = 3
0 = "Maria"
1 = "Jose"
2 = "Juan"
You are assigning local reference of object to obj (won't copy the values)
obj = object; // means, student = object
no change will be reflected outside the scope of the consumer, instead, you need to modify the state using setters as:
((Student) obj).setName(((Student) object).getName());
obj = object; // after this point, student object won't be accessible in the current scope.
Note: You should have getters and setters to access private properties outside Student class, and this example just demonstrates the working by assigning name property.
Reference:
• Classes and Object
The String variable finalMapSearchUrl gets concatenated with another String (mapUrlParam) in the constructor and the Log shows the expected value : Final map URL : https://www.google.com/maps/search/?api=1&query=Spilia%20Beach (here the mapUrlParam = Spilia Beach). However, when i call the getMapSearchUrl() method from outside the class and monitor the Log, the finalMapSearchUrl's value is now back to the default https://www.google.com/maps/search/?api=1&query=. Log in getMapSearchUrl() : finalMapSearchUrl = https://www.google.com/maps/search/?api=1&query=. Any ideas on when,why and how it's value is not preserved outside of the constructor?
PlaceObject.java class:
public class PlaceObject implements Parcelable { // Implementing the Parcelable interface to allow for cleaner and faster code
private static final String TAG = PlaceObject.class.getSimpleName();
private static final String baseMapSearchUrl = "https://www.google.com/maps/search/?api=1&query="; // Base url for launching a Map activity with a Search Intent
// Using int so that the values can be accessed via R.string etc.
private int name;
private int description;
private int category;
private String locationDistance;
private String finalMapSearchUrl = baseMapSearchUrl;
PlaceObject(int name, int description, int category , String locationDistance, String mapUrlParam) {
this.name = name;
this.description = description;
this.locationDistance = locationDistance;
this.category = category;
finalMapSearchUrl += Uri.encode(mapUrlParam);
Log.d(TAG,"Final map URL : " + finalMapSearchUrl);
}
private PlaceObject(Parcel in) {
name = in.readInt();
description = in.readInt();
locationDistance = in.readString();
category = in.readInt();
}
public static final Creator<PlaceObject> CREATOR = new Creator<PlaceObject>() {
#Override
public PlaceObject createFromParcel(Parcel in) {
return new PlaceObject(in);
}
#Override
public PlaceObject[] newArray(int size) {
return new PlaceObject[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(name);
parcel.writeInt(description);
parcel.writeString(locationDistance);
parcel.writeInt(category);
}
public int getName() {
return name;
}
public int getDescription() {
return description;
}
public String getLocationDistance() {
return locationDistance;
}
public int getCategory() {
return category;
}
public String getMapSearchUrl() {
Log.d(TAG,"finalMapSearchUrl = " + finalMapSearchUrl);
return finalMapSearchUrl; //TODO:sp figure out why the variable's value gets lost after the constructor is done
}
}
Because you're simply getting the base url and not the one Parceled.
Solution:
Add it to parcel and pay attention to the order of writing,
Like this:
private PlaceObject(Parcel in) {
name = in.readInt();
description = in.readInt();
category = in.readInt();
locationDistance = in.readString();
finalMapSearchUrl = in.readString();
}
and don't forget to fix this as well:
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(name);
parcel.writeInt(description);
parcel.writeInt(category);
parcel.writeString(locationDistance);
parcel.writeString(finalMapSearchUrl);
}
I just want to sort my data by using sort and compare two value.
Here is my code:
ArrayAdapter arrayAdapter = new ArrayAdapter(getApplicationContext(), android.R.layout.simple_list_item_1, myData);
arrayAdapter.sort(myData, new Comparator<myData>() {
#Override
public int compare(myData o1, myData o2) {
return Integer.compare(o1.getFinalScore(), o2.getFinalScore());
}
});
arrayAdapter.notifyDataSetChanged();
dataList.setAdapter(arrayAdapter);
But I got the error said sort(java.util.Comparator) in ArrayAdapter cannot be applied to (java.lang.string[], anonymousjava.util.Comparator)
Can anyone tell what is the problem??
myData class
public class myData {
public int getFinalScore() {
return finalScore;
}
public void setFinalScore(int finalScore) {
this.finalScore = finalScore;
}
private String customeName;
private String carName;
private String appointmentDate;
private String email;
private String issueDescribe;
private String timeForJob;
private String costForJob;
private String reliableOnCar;
private String distanceJob;
private int finalScore;
public myData(String customeName, String carName, String appointmentDate, String email, String issueDescribe, String timeForJob, String costForJob,
String reliableOnCar, String distanceJob, int finalScore) {
this.customeName = customeName;
this.carName = carName;
this.appointmentDate = appointmentDate;
this.email = email;
this.issueDescribe = issueDescribe;
this.timeForJob = timeForJob;
this.costForJob = costForJob;
this.reliableOnCar = reliableOnCar;
this.distanceJob = distanceJob;
this.finalScore = finalScore;
}
}
If you look at the sort() documentation for an ArrayAdapter, you can see that it takes only one argument, a comparator.
So you have to update your code like this :
arrayAdapter.sort(new Comparator<myData>() {
#Override
public int compare(myData o1, myData o2) {
return Integer.compare(o1.getFinalScore(), o2.getFinalScore());
}
});
Hope it helps !
I am creating the ArrayList of Object, to insert information I use different constructors in that class but I have one type variable that I update with every constructor call. here is what i am doing
public class eProperty {
public String type = null;
public int marks;
public int code;
public String category
public String student_name = null;
public String employee_name = null;
public String o_name = null;
public eProperty(String type, String student_name, int marks) {
this.marks = marks;
this.type = type;
this.student_name = student_marks;
}
public eProperty(String type, String employee_name, int makrs, String category) {
this.marks = marks;
this.type = type;
this.employee_name = employee_name;
this.category = category;
}
public eProperty(String type, int code, int makrs, String o_name) {
this.marks = marks;
this.type = type;
this.mnc = code;
this.o_name = o_name;
}
}
I populate arraylist like this,
ArrayList<eProperty> allData;
eProperty data;
if(type.equals("Student")) {
data = new eProperty(type, "John", 45)
allData.add(data)
}
if(type.equals("Employee")){
data = new eProperty(type, "Vicky", 86, "Developer")
allData.add(data)
} ... other cases also handled like this
Now I want to retrive highest marks for each type and I am stuck here, any help
Thanks
Using loop (sorry for that...) and Predicate from Apache Commons
public static int getHighestMarkByType(ArrayList<eProperty> allData, String type) {
Predicate predicate = new Predicate() {
public boolean evaluate(Object data) {
if ((eProperty) data).getType().equals(type)) {
return true;
} else {
return false;
}
}
};
ArrayList<eProperty> filteredData = (ArrayList<eProperty>) CollectionUtils.select(allData,predicate);
int maxMarks = 0;
for (eProperty data : filteredData) {
if (data.getMarks() > maxMark) {
maxMarks = data.getMark();
}
}
return maxMarks;
}
How to solve the following constructor overloading problem? This is an interview question but I am curious to know the solution.
class Player
{
int nationalRank;
int internationalRank;
String name;
Player(String name, int nationalRank)
{
this.name= name;
this.nationalRank = nationalRank;
this.internationalRank=0;
}
Player(String name, int internationalRank)
{
this.name= name;
this.nationalRank = 0;
this.internationalRank=internationalRank;
}
}
Here, the compiler will give an error because argument types are same for both constructor. But logically they both are different. How can I solve this problem without adding any extra arguments? Is there any design pattern specifically for this?
class Player
{
int nationalRank;
int internationalRank;
String name;
private Player(){}
public static Builder builder()
{
return new Builder();
}
public static class Builder
{
int nationalRank = -1;
int internationalRank = -1;
String name;
public Builder nationalRank(int nationalRank)
{
this.nationalRank = nationalRank;
return this;
}
public Builder internationalRank(int internationalRank)
{
this.internationalRank = internationalRank;
return this;
}
public Builder name(String name)
{
this.name = name;
return this;
}
public Player build()
{
if (nationalRank == -1 && internationalRank = -1)
throw new IllegalStateException("both ranks haven't been initialized");
if (null == name)
throw new IllegalStateException("name hasn't been initialized");
Player result = new Player();
result.nationalRank = this.nationalRank;
result.internationalRank = this.internationalRank;
result.name = this.name;
return result;
}
}
}
Usage:
Player player = Player.builder().name("John").internationalRank(522).build();
You've got various options.
The simplest is to add factory methods like this:
public class Player
{
private int nationalRank;
private int internationalRank;
private String name;
private Player()
{
}
public static Player newNationalPlayer(String name, int nationalRank)
{
Player nationalPlayer = new Player();
nationalPlayer.name= name;
nationalPlayer.nationalRank = nationalRank;
nationalPlayer.internationalRank = 0;
return nationalPlayer;
}
public static Player newInternationalPlayer(String name, int internationalRank)
{
Player internationalPlayer = new Player();
internationalPlayer.name= name;
internationalPlayer.nationalRank = 0;
internationalPlayer.internationalRank = internationalRank;
return internationalPlayer;
}
...
}
However, this leaves an unused variable which isn't very nice. A better solution would be to add a PlayerType enum:
public enum PlayerType
{
NATIONAL,
INTERNATIONAL
}
public class Player
{
private int rank;
private String name;
private PlayerType type;
public Player(String name, PlayerType type, int rank)
{
this.name= name;
this.type = type;
this.rank = rank;
}
...
}
Which is best is down to the exact use case.
Just reverse the parameters of one of the constructors and you are good to go.... I made this answer thinking that it's an interview question....perhaps the interviewer has this in mind...
class Player
{
int nationalRank;
int internationalRank;
String name;
Player(String name, int nationalRank)
{
this.name= name;
this.nationalRank = nationalRank;
this.internationalRank=0;
}
Player( int internationalRank,String name)
{
this.name= name;
this.nationalRank = 0;
this.internationalRank=internationalRank;
}
}
As suggested by a comment, just use static factory methods. In fact, this solution goes further than that and uses a builder. You will note a clear advantage: all instance variables are now final.
public class Player
{
private final String name;
private final int nationalRank;
private final int internationalRank;
// Constructor becomes private
private Player(final Builder builder)
{
name = builder.name;
nationalRank = builder.nationalRank;
internationalRank = builder.internationalRank;
}
public static Builder withName(final String name)
{
return new Builder(name);
}
// Inner builder class
public static class Builder
{
private final String name;
private int nationalRank;
private int internationalRank;
private Builder(final String name)
{
this.name = name;
}
public Builder withNationalRank(int rank)
{
nationalRank = rank;
return this;
}
public Builder withInternationalRank(int rank)
{
internationationalRank = rank;
return this;
}
public Player build()
{
return new Player(this);
}
}
}
Usage:
Player player1 = Player.withName("foo").withNationalRank(1).build();
// etc