Returning Optional<Student> or Optional.empty() - java-8

I'm playing a little bit with Optional to understand how it works. Let's say I have this class:
public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I want to return a Student by Id or Optional.empty if it doesn't find it. This is what I have so far:
public class Main {
static List<Student> students = new ArrayList<>();
public static void main(String[] args) {
students.add(new Student(1, "name1"));
students.add(new Student(2, "name2"));
students.add(new Student(3, "name3"));
System.out.println(getStudentById(1).get().getName());
}
public static Optional<Student> getStudentById(int id) {
return students
.stream()
.filter( s -> s.getId() == id)
.findFirst();
}
}
That works but I wanted to add this line:
.findFirst()
.orElse(Optional.empty());
and I got this:
Error:(23, 39) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.Optional conforms to com.company.Student
Also I'd like to know if that is the correct way to go over a list, I mean element by element or there is something better?

If you read javadocs of Stream#findFirst() you will find that you already have what you need:
Returns an Optional describing the first element of this stream, or an
empty Optional if the stream is empty. If the stream has no encounter
order, then any element may be returned.
So just do
return students
.stream()
.filter( s -> s.getId() == id)
.findFirst();

Related

Android room. error: Cannot figure out how to read this field from a cursor

the SQLite database contains three tables 1) employee 2) skills 3) departments. The idea is this - the employee table stores data such as id, name, last_name, salary. Also, an employee has data such as skill and department, but there can be several data for one employee, so I created two separate skills and departments tables and linked them using the key to the employee table where the primary key for employee is id. Now with the help of id I need to display all the information about employee including his skills which can be several and departments. I implement the whole process using the ROOM library.
Here is the request I make
#Query("SELECT employ.id ,employ.name ,employ.last_name, employ.salary, " +
"skill.skill, department.department_name FROM employ INNER JOIN skill,department " +
"ON employ.id = :id AND skill.employ_id = :id AND department.employ_id = :id ")
AllAboutEmployee getAllAboutEmployee(String id);
Here is the AllAboutEmployee class whose object accepts the result of the request
public class AllAboutEmployee {
#ColumnInfo(name = "id")
private String id;
#ColumnInfo(name = "name")
private String name;
#ColumnInfo(name = "last_name")
private String lastName;
#ColumnInfo(name = "salary")
private String salary;
#ColumnInfo(name = "department_name")
private List<String> departmentsList; // THE ERROR IS ON THIS LINE
#ColumnInfo(name = "skill")
private List<String> skillList; // THE ERROR IS ON THIS LINE
public AllAboutEmployee(String id, String name, String lastName, String salary, List<String> departmentsList, List<String> skillList) {
this.id = id;
this.name = name;
this.lastName = lastName;
this.salary = salary;
this.departmentsList = departmentsList;
this.skillList = skillList;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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 getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public List<String> getDepartmentsList() {
return departmentsList;
}
public void setDepartmentsList(List<String> departmentsList) {
this.departmentsList = departmentsList;
}
public List<String> getSkillList() {
return skillList;
}
public void setSkillList(List<String> skillList) {
this.skillList = skillList;
}
}
So ther are two fields int the AllAboutEmployee class with the List type, in order to put several skills and several departments there. It is in these fields that an error occurs. Thank you in advance for your help
Wow.. that's so cool.. I was coding all day and got this error too!
You have to create a TypeCoverter to store your data into your Room's Database.
In this case you have two List, that are not types recognizable by Database, so you have to create an Converter for it to store as a String, and another method to do the inverse.
Something like:
class TypeCoverter{
#TypeConverter
fun arrayListToString(arrayList: ArrayList<String>?): String? {
if (arrayList.isNullOrEmpty()) return null
val string = StringBuilder()
for (item in arrayList) {
val isNotTheLastItemInTheArrayList = (item == arrayList.last()).not()
if (isNotTheLastItemInTheArrayList) {
string.append(item).append(COMMA)
} else {
string.append(item)
}
}
return string.toString()
}
}
#TypeConverter
fun stringToArrayList(string: String?): ArrayList<String>? {
when {
string.isNullOrEmpty() -> {
return null
}
string.contains(COMMA).not() -> {
val list = ArrayList<String>()
list.add(string)
return list
}
else -> {
return string.split(COMMA.toRegex()).dropLastWhile { it.isEmpty() } as ArrayList<String>
}
}
}
That's actually in Kotlin, but you can see how it works.

how to convert integer to string using typeconverters in room android?

I am developing a chat app but I am getting the following error: Cannot find getter for the field.
that's why I want to convert Integer to String using type converters in Room but I did not find any sample below my User.java model class
#Entity public class User implements IChatUser {
#PrimaryKey(autoGenerate = true)
private Integer id;
#ColumnInfo(name = "name")
private String name;
#Ignore
Bitmap icon;
public User() {
}
#Ignore
public User(String name, Bitmap icon) {
this.name = name;
this.icon = icon;
}
#Override
public Integer getId() {
return this.id;
}
#Override
public String getName() {
return this.name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
#Override
public Bitmap getIcon() {
return this.icon;
}
#Override
public void setIcon(Bitmap icon) {
this.icon = icon;
} }
below IchatUser.kt
interface IChatUser {
fun getId(): String
fun getName(): String?
fun getIcon(): Bitmap?
fun setIcon(bmp: Bitmap)
}
To create a #TypeConverter create a java class and call it IntConverter
public class IntConverter {
#TypeConverter
public static String toString(int number) {
return number == null ? null : Integer.toString(number);
}
#TypeConverter
public static int toInt(String str) {
return str == null ? null : Integer.parseInt(str);
}
}
Now you need the database to know about this TypeConverter so declare this:
#TypeConverters(IntConverter.class)
Just below the #Database annotation in the Database class

Sonar gives NullPointerException not right

I am having java code:
public class Test {
public static void main(String[] args) {
Student student = new Student(1,"test");
printId(student);
}
private static void printId(Student obj) {
if(Objects.isNull(obj))
return;
System.out.println("Id: " + obj.getId());
}
}
public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId(){
return id;
}
}
At line System.out.println... sonar is showing that obj can be null but I had already checked for null value.
Is there any way to get rid of this issue?
You could use explicit null test.
if(null==obj)
return;
......
The rule itself does not recognize usage of Objects.isNull as null check. Objects.isNull(Object obj) returns result of null==obj expresion so it can be safely replaced.
However you could contact SonarSource and propose rule change.

#ApiModelProperty(hidden = true) is ignored on join columns

#ApiModelProperty(hidden = true) is ignored if the property is a Class. My problem is that it expands too much and a leaf field becomes required.
Is there a way to make it work? Or the only solution is to make a different class for request usages?
A simple example:
public class Child {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Parent {
private String name;
#ApiModelProperty(hidden = true)
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
If I put #ModelAttribute over Parent, in rest endpoint swagger will render the child.name field in the request.

Accessing Subclass properties in a JavaFX TableView ObservableArrayList

I am trying to access getter properties in a subclass with a TableView in JavaFX. I have the following class:
public class PersonType implements Serializable {
private static final long serialVersionUID = 1L;
Person person;
short count;
public PersonType() {
}
public PersonType(Person person, short count) {
super();
this.person = person;
this.count = count;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public short getCount() {
return count;
}
public void setCount(short count) {
this.count = count;
}
Person is like this:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
String firstName;
String lastName;
public Person() {
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Okay - lastly we have the following:
#FXML
private TableColumn tcFirstName;
#FXML
private TableColumn tcLastName;
#FXML
private TableView tblPersonTypes;
ArrayList<PersonType> pType = new ArrayList<PersonType>();
//Can assume that pType here has say 5 entries, the point of this
//is I'm trying to get to the firstName, lastName properties of the
//PersonType in the TableView below like the following:
tcFirstName.setCellValueFactory(new PropertyValueFactory<String,String>("firstName"));
tcLastName.setCellValueFactory(new PropertyValueFactory<String,String>("lastName"));
//Populate Table with Card Records
ObservableList<PersonType> data = FXCollections.observableArrayList(pType);
tblPersonTypes.setItems(data);
And I'm unsure how with a list of PersonTypes I can tell the table columns that I want the firstName and lastName properties of the Person object contained within. I know I could create a new object, and have the "count" from PersonTypes, then the other properties of "firstName", "lastName" etc without having an object property of Person. Any help would be greatly appreciated.
-- EDIT --
Another way I thought to do this was using CellFactories - where I would pass in to the CellValueFactories the Person object, then set the CellFactory to return a String value (firstName for the first name column, etc). And it would look like this:
tcFirstName.setCellValueFactory(new PropertyValueFactory<Person,String>("person"));
tcFirstName.setCellFactory(new Callback<TableColumn<Person,String>,TableCell<Person,String>>(){
#Override
public TableCell<Person,String> call(TableColumn<Person,String> param) {
TableCell<Person,String> cell = new TableCell<Person,String>(){
#Override
public void updateItem(String item, boolean empty) {
if(item!=null){
setGraphic(new Label(item.getFirstName()));
}
}
};
return cell;
}
});
Try this:
tcFirstName.setCellValueFactory(new Callback<CellDataFeatures<PersonType, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<PersonType, String> p) {
// p.getValue() returns the PersonType instance for a particular TableView row
if (p.getValue() != null && p.getValue().getPerson() != null) {
return new SimpleStringProperty(p.getValue().getPerson().getFirstName());
} else {
return new SimpleStringProperty("<No TC firstname>");
}
}
});
}

Resources