How the toString() is working with Predicate in the following program - java-8

Can anybody please explain how the toString() function is working with this Predicate. I understood the lambda expression but how the toString() function is called.
import java.util.function.*;
import java.util.*;
class Demo{
public static void main(String arv[]){
HashSet <Employee> hs = new HashSet<>();
hs.add(new Employee("A",40000,25,"CSE"));
hs.add(new Employee("B",50000,26,"CSE"));
hs.add(new Employee("C",54000,30,"ECEadsa"));
hs.add(new Employee("D",45000,25,"ECE"));
hs.add(new Employee("E",60000,32,"CSE"));
Predicate <Employee> emp = t -> t.salary > 50000;
Predicate <Employee> emp1 = emp.and( t -> t.department.length()>5);
for(Employee e: hs)
if (emp1.test(e))
System.out.println(e);
}
}
class Employee{
String name;
double salary;
int age;
String department;
Employee(String n, double s, int a, String d){
name = n;
salary = s;
age = a;
department = d;
}
public String toString(){
return " name = "+name+" salary = "+salary+" age = "+age+" department = "+department;
}
}
Output:
name = C salary = 54000.0 age = 30 department = ECEadsa

You have added code for printing Employee, When ever you print any object toString() method is called for that class if present else toString of parent is called
for(Employee e: hs)
if (emp1.test(e))
System.out.println(e);
}
}
For Employee with department.length() > 5 printing logic System.out.println(e); is called

In the PrintStream class the println(Object x) method uses String.valueOf(x), which invokes the toString() of the object.
If you had not overwritten the toString() method, you would use the default implementation of the Object class.

Related

How to count the iteration of lambda in Java streams

I have below solution with counter variable, is there any preferred way to get the counter of lambda iteration ?
class Employee {
String name;
int salary;
}
public class Calculator {
private static Integer counter;
public void method1() {
counter = 0; // Instead of this, is there any default counter ?
List<Employee> emp = getData()
List<Employee> updated = emp.stream().map(Calculator::increaseSalary).collect(Collectors.toList());
System.out.println("counter = " + counter);
}
private Employee increaseSalary(Employee emp) {
counter++;
emp.setSalary(50000);
return emp;
}
}

How can we use comparable for sorting with lambda expression in java 8?

In the Custom class Student implements Comparable<Student> class, if don't override public int compareTo(Student o) the method then it is giving compile-time error.
So my query is even comparable is a functional interface. Then why we are not able to achieve the functional programming in the case of comparable.
import java.util.ArrayList;
public class Student implements Comparable<Student> {
int rollno;
String name;
int age;
Student(int rollno, String name, int age) {
this.rollno = rollno;
this.name = name;
this.age = age;
}
#Override
public String toString() {
return "Student [rollno=" + rollno + ", name=" + name + ", age=" + age + "]";
}
#Override
public int compareTo(Student o) {
return 0;
}
public static void main(String[] args) {
ArrayList<Student> al=new ArrayList<Student>();
al.add(new Student(101,"Vijay",23));
al.add(new Student(106,"Ajay",27));
al.add(new Student(105,"Jai",21));
//Here I want to write my lambda expression using Comparable
}
}
I found the answer in Java Book Chapter 3 [144 page] (https://www.amazon.com/dp/1119067901)

getting an error in unboxing in c# stating name does not exist in current context?

class Program
{
static void Main(string[] args)
{
Console.WriteLine("enter id");
int id = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("enter name");
string name = Console.ReadLine();
Console.WriteLine("price");
int price = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("enter quantity");
int quantity = Convert.ToInt32(Console.ReadLine());
product_demo p1 = new product_demo(id, name, price, quantity);
p1.diplay();
Console.Read();
}
}
public class product_demo
{
public int id;
public string name;
public int price;
public int quantity;
public product_demo(int id, string name, int price, int quantity)
{
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
object o1 = id;
object o2 = name;
object o3 = price;
object o4 = quantity;
}
public void diplay()
{
int j = (int)o1;
Console.WriteLine("id :");
}
}
getting an error while unboxing in display function. boxing is done in product_demo constructor. one more question ; can we define boxing outside any constructor or methods, directly in body of class.
You have created object o1 in the constructor of product_demo and therefore it exists only within that scope. You need to have your objects within the class (Similar to where you have placed your other variables such as int id, string name, etc.

Comparing dates in ascending and descending order in arrayList not working

I have an array of email objects. I need to sort them by two fields. the first field is by subject, which i have working, and the other is by date which I cannot get. I tried a bunch of other people's solutions but nothing seems to work. Here is an excerpt of my code:
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Comparator;
import java.util.Date;
public class Email implements Comparable{
private String to;
private String cc;
private String bcc;
private String subject;
private String body;
private GregorianCalendar timestamp; //time that email was created
//constructors and getters and setters (besides timeStamp) omitted to save space
public Date getTimestamp() {
return timestamp.getTime();
}
public void setTimestamp(GregorianCalendar timestamp) {
this.timestamp = timestamp;
}
//This works
public static Comparator<Email> emailSubjectComparatorAscending = new Comparator<Email>(){
public int compare(Email e1, Email e2) {
String EmailSubject1 = e1.getSubject().toLowerCase();
String EmailSubject2 = e2.getSubject().toLowerCase();
return EmailSubject1.compareTo(EmailSubject2);
}
};
//This works
public static Comparator<Email> emailSubjectComparatorDescending = new Comparator<Email>(){
public int compare(Email e1, Email e2) {
String EmailSubject1 = e1.getSubject().toLowerCase();
String EmailSubject2 = e2.getSubject().toLowerCase();
return EmailSubject2.compareTo(EmailSubject1);
}
};
//This doesn't work
public static Comparator<Email> emailDateComparatorAscending = new Comparator<Email>(){
#Override
public int compare(Email o1, Email o2) {
if(o1.getTimestamp().equals(o2.getTimestamp()))
return 0;
if(o2.getTimestamp().before(o1.getTimestamp()))
return 1;
else
return -1;
}
};
//This doesn't work
public static Comparator<Email> emailDateComparatorDescending = new Comparator<Email>(){
#Override
public int compare(Email o1, Email o2) {
if(o1.getTimestamp().equals(o2.getTimestamp()))
return 0;
if(o1.getTimestamp().before(o2.getTimestamp()))
return 1;
else
return -1;
}
};
#Override
public String toString(){
return("To: " + to + "\nCC: " + cc + "\nBCC: " + bcc + "\nSubject: " + subject + "\n" + body);
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
here is the part of my other class, in which I call these sorting methods:
import java.util.*;
public class Folder{
private ArrayList<Email> emails; //initialize?
private String name;
private String currentSortingMethod; //default = descending
public Folder(String name) {
super();
this.name = name;
currentSortingMethod = "sortByDateDescending";
emails = new ArrayList<Email>(); //instantiate the arrayList
}
//omitted getters, setters and other irrelevant methods
//This works
public void sortBySubjectAscending(){
Collections.sort(emails, Email.emailSubjectComparatorAscending);
currentSortingMethod = "sortBySubjectAscending";
}
//This works
public void sortBySubjectDescending(){
Collections.sort(emails, Email.emailSubjectComparatorDescending);
currentSortingMethod = "sortBySubjectDescending";
}
//This doesn't work
public void sortByDateAscending(){
Collections.sort(emails, Email.emailDateComparatorAscending);
currentSortingMethod = "sortByDateAscending";
}
//This doesn't work
public void sortByDateDescending(){
Collections.sort(emails, Email.emailDateComparatorDescending);
currentSortingMethod = "sortByDateDescending";
}
I am really confused with this and I have tried so many different ways and none work. If anyone could explain how to make this work I would appreciate it greatly

How to use static constructor reference with a three parameters Java 8 Function (without make TriFunction)?

I am currently playing with Java 8 and I found a problem with Function. I would like ton know if there is a way to use function reference (name::methode) with a Function with tree parameters without declare a new functional interface (i.e. TriFunction).
I tried with currying way, but it doesn't work.
I have three classes :
Person.class
public class Person {
public enum Sex {
MALE, FEMALE
}
private String firstName;
private String lastName;
private Sex gender;
public Person(String firstName, String lastName, Sex gender) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Sex getGender() {
return gender;
}
}
PersonFactory
public class PersonFactory {
public static Person create(String firstName, String lastName, String gender) {
// Check firstName Parameter
if(firstName == null || firstName.isEmpty()) {
throw new IllegalArgumentException("The firstName argument expect to not be null or empty");
}
// Check lastName Parameter
if(lastName == null || lastName.isEmpty()) {
throw new IllegalArgumentException("The lastName argument expect to not be null or empty");
}
// Check gender Parameter
if(gender == null || gender.isEmpty()) {
throw new IllegalArgumentException("The gender argument expect to not be null or empty");
} else {
switch(gender) {
case "M":
return new Person(firstName, lastName, Sex.MALE);
case "F":
return new Person(firstName, lastName, Sex.FEMALE);
default:
throw new IllegalArgumentException("The gender parameter is supposed to be either 'M' for male or 'F' for Female");
}
}
}
}
CsVPersonParser
public class CsvPersonParser {
public Person parseLine(String line, String separator, Function<String, Function<String, Function<String, Person>>> creator) {
String[] separedLine = line.split(separator);
String firstName = separedLine[0];
String lastName = separedLine[1];
String gender = separedLine[2];
return creator.apply(firstName).apply(lastName).apply(gender);
}
}
Here is my main class :
public class App {
public static void main(String[] args) {
final String IMAGINARY_CSV_FILE_LINE = "Jean,Dupont,M";
CsvPersonParser csvParser = new CsvPersonParser();
csvParser.parseLine("blabla", ",", PersonFactory::create);
}
}
The compilator show : The type PersonFactory does not define create(String) that is applicable here
It seems pretty logical. I have no solution. Is anyone can help me ?
I wonder why there is no way to do it simple without to create new things.
Probably a tri function is quite complex. I suggest that you use a builder to create a person.
The main reasons are, that you are not fixed on parameter ordering and you can extend your person. When you use a trifunction where all parameters are strings its often hard to say which parameter is the first/second/third. And when you want to add an address to a person it becomes more difficult to make it with generic classes like TriFunction.
My suggestion:
public interface PersonBuilder {
PersonBuilder withFirstName(String firstName);
PersonBuilder withLastName(String lastName);
PersonBuilder withGender(String gender);
Person create();
}
Concrete Implementation:
public class DefaultPersonBuilder implements PersonBuilder {
private String firstName;
private String lastName;
private String gender;
#Override
public PersonBuilder withFirstName(String firstName) {
this.firstName = firstName;
return this;
}
#Override
public PersonBuilder withLastName(String lastName) {
this.lastName = lastName;
return this;
}
#Override
public PersonBuilder withGender(String gender) {
this.gender = gender;
return this;
}
#Override
public Person create() {
// Check firstName Parameter
if (firstName == null || firstName.isEmpty()) {
throw new IllegalArgumentException("The firstName argument expect to not be null or empty");
}
[... your implementation using the fields]
}
}
Your parser method:
public Person parseLine(String line, String separator, PersonBuilder person) {
String[] separedLine = line.split(separator);
String firstName = separedLine[0];
String lastName = separedLine[1];
String gender = separedLine[2];
return person.withFirstName(firstName).withLastName(lastName).withGender(gender).create();
}
Now you can change the argument order oder add new fields to person without creating a function with 10 parameters. The parser interface is simpler now, too.
There is no way to do that what I wanted. However two other solutions is possible. Use a lambda instead of PersonFactory::create or create a new functional interface.
Here is the result :
New functional interface
#FunctionalInterface
public interface TriFunction<A, B, C, D> {
public D apply(A a, B b, C c);
}
Add a function parseLine with my new functional interface
public class CsvPersonParser {
// Currying style
public Person parseLine(String line, String separator, Function<String, Function<String, Function<String, Person>>> creator) {
String[] separedLine = line.split(separator);
String firstName = separedLine[0];
String lastName = separedLine[1];
String gender = separedLine[2];
return creator.apply(firstName).apply(lastName).apply(gender);
}
// New Functionnal interface style
public Person parseLine(String line, String separator, TriFunction<String, String, String, Person> creator) {
String[] separedLine = line.split(separator);
String firstName = separedLine[0];
String lastName = separedLine[1];
String gender = separedLine[2];
return creator.apply(firstName, lastName, gender);
}
}
My main class with solutions
public class App {
public static void main(String[] args) {
final String DATA_FILE_SEPARATOR = ",";
final String FAKE_CSV_LINE = "Jean,Dupont,M";
CsvPersonParser csvParser = new CsvPersonParser();
Person person;
// Use curryling style
person = csvParser.parseLine(FAKE_CSV_LINE, DATA_FILE_SEPARATOR, f -> l -> g -> PersonFactory.create(f, l, g));
System.out.println("Currying style : " + person.getFirstName() + " " + person.getLastName() + " " + person.getGender());
// Use new functionnal interface
person = csvParser.parseLine(FAKE_CSV_LINE, DATA_FILE_SEPARATOR, PersonFactory::create);
System.out.println("TriFunction style : " + person.getFirstName() + " " + person.getLastName() + " " + person.getGender());
// Use lambda style
person = csvParser.parseLine(FAKE_CSV_LINE, DATA_FILE_SEPARATOR, (a,b,c) -> PersonFactory.create(a, b, c));
System.out.println("Lambda style : " + person.getFirstName() + " " + person.getLastName() + " " + person.getGender());
}
}

Resources