I have a list of maps. The map holds two values "key" and "value" I have to filter out specific values from that list. So I am iterating through the list and if the map has the key that I want, then I take that value and set it in another pojo.
{
teams=["
{key=NAME, value="ANKIT"},
{key=START_DATE, value=2016-09-01}
}
String START_DATE = "START_DATE";
STRING NAME = "NAME";
I have multiple conditions to check. I am doing this using foreach. Can this be done using Java 8 stream().
teamList.forEach(
team -> {
if (NAME.equals(team.get("key"))) {
team.setName(team.get("value"));
} else if (START_DATE.equals(team.get("key"))) {
team.setEndDate(LocalDate.parse(team.get("value")));
}
});
You can't use Java 8 new features to replace your old Java code. I think as everyone was trying to point out that fact what you are trying is not a recommended use of Java 8 streams.
Best practice in Java 8 is to avoid state-full operations. (That means, you are modifying an existing object. Here in this case, you are setting data to a object that resides in memory which had created earlier)
If you still wants to write this simple logic using Java 8 streams, below you can see the POJO class and the main method that sets the Data to that object.
public class POJO {
private Integer age;
private LocalDate birthday;
public LocalDate getBirthday() {
return birthday;
}
public void setBirthday(LocalDate birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
#Override
public String toString() {
return "POJO{" +
"age=" + age +
", birthday=" + birthday +
'}';
}
}
public class MapIteration {
public static Map<String,Integer> ageMap = new HashMap<>();
private static final String NAME = "Doki";
private static final String START_DATE = "31/10/2016";
private static POJO myDataObject = new POJO();
private static BiConsumer<String,Integer> integerConsumer = (k, v) -> {
try {
if(NAME.equals(k.toString()))
myDataObject.setAge(Integer.valueOf(v.toString()));
else if (START_DATE.equals(LocalDate.parse(k.toString()).toString()))
myDataObject.setBirthday(LocalDate.parse(k.toString()));
} catch (NumberFormatException | DateTimeParseException e) {
System.out.println("exception occurred: Because sometimes names cannot be parsed as Date formats");
}
};
static{
ageMap.put("John", 23);
ageMap.put("Norman", 26);
ageMap.put("Micheal", 25);
ageMap.put("Doki", 22);
}
public static void main(String[] args){
ageMap.forEach(integerConsumer);
System.out.println(myDataObject);
}
}
Related
In the first part of my code I am reading data from a file and putting the fields into variables like this
Date date = rs.getDate(1);
Integer flightnumber = rs.getInt("FlightNumber");
Integer passengers = rs.getInt("Passengers");
so I need to put these variables into an ArrayList for example and then write a method that compares two variables with the ones in the list I created and returns an int being the passengers.
public int getPassengerNumbersFor(int flightNumber, LocalDate date)
The tricky part is that I cannot create any new classes and there isn't any getFlightNumber/ getDate implemented nor am I allowed to code one. I have been told that a HashMap can be used but in this case I would have one key and two values which wouldn't work (passengers is key, flightnumber and date are values maybe).
How can I store these 3 values and then write my method?
If you were "allowed" to create classes, I would suggest an immutable class:
public class Flight {
private final LocalDate localDate;
private final int number;
private final List<Passenger> passengers;
public Flight(LocalDate localDate, int number, List<Passenger> passengers) {
this.localDate = localDate;
this.number = number;
this.passengers = List.copyOf(passengers);
}
public LocalDate getLocalDate() {
return localDate;
}
public int getNumber() {
return number;
}
public List<Passenger> getPassengers() {
return passengers;
}
public int getPassengersNumber() {
return passengers.size();
}
...
}
Note the usage of the new Date-Time API.
And then you could have another class for all the flights:
public class Flights {
private final List<Flight> flights;
public Flights(List<Flight> flights) {
this.flights = new ArrayList<>(flights);
}
public Flight getFlight(LocalDate localDate, int number) {
return flights.stream()
.filter(flight -> flight.getLocalDate().equals(localDate))
.filter(flight -> flight.getNumber() == number)
.findAny()
.orElseThrow(InvalidFlightException::new);
}
public void addFlight(Flight flight) {
flights.add(flight);
}
...
}
We use the builder pattern extensively in our code base, with built objects all having a toBuilder() method. I want to write a unit test that ensures that no fields have been forgotten in the toBuilder() methods, i.e., for any buildable object, I want to a test roughly like this
MyClass obj = getTestObjectWithRandomData();
assertEquals(obj, obj.toBuilder().build());
Now, I can fairly easy write a basic version of getTestObjectWithRandomData() that uses reflection to assign a bunch of values to the fields of any object. However, the snag is that build() often contains tons of validation checks that will throw exceptions if, for example, a certain integer isn't within a sane range. Writing a generalized version of getTestObjectWithRandomData() that conforms all those class-specific validation checks would be impossible.
So, how can I do what I want to do? I'm tempted to segregate the construction and validation code into different methods so that the test doesn't trip on the validation, but then that means that people have to remember to call validate() or whatever on objects after they create them. Not good.
Any other ideas?
How about using Lombok? Would that be an option for you? It will auto-generate the builder code and you'll never again have to worry about it.
https://projectlombok.org/features/Builder
Simply annotate your classes with #Builder
With Lombok
import lombok.Builder;
import lombok.Singular;
import java.util.Set;
#Builder
public class BuilderExample {
private String name;
private int age;
#Singular private Set<String> occupations;
}
Vanilla Java
import java.util.Set;
public class BuilderExample {
private String name;
private int age;
private Set<String> occupations;
BuilderExample(String name, int age, Set<String> occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}
public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}
public static class BuilderExampleBuilder {
private String name;
private int age;
private java.util.ArrayList<String> occupations;
BuilderExampleBuilder() {
}
public BuilderExampleBuilder name(String name) {
this.name = name;
return this;
}
public BuilderExampleBuilder age(int age) {
this.age = age;
return this;
}
public BuilderExampleBuilder occupation(String occupation) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.add(occupation);
return this;
}
public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.addAll(occupations);
return this;
}
public BuilderExampleBuilder clearOccupations() {
if (this.occupations != null) {
this.occupations.clear();
}
return this;
}
public BuilderExample build() {
// complicated switch statement to produce a compact properly sized immutable set omitted.
// go to https://projectlombok.org/features/Singular-snippet.html to see it.
Set<String> occupations = ...;
return new BuilderExample(name, age, occupations);
}
#java.lang.Override
public String toString() {
return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}
}
}
my first post here & I'm only starting to learn Java so please bear with me.
I have a HashMap which stores a key and an instance of a class as the corresponding value (from a class I called Main). The object has a two variables. What I'd like to do is to get a print out based on a particular object variable, in this example by year. Here is my code:
public class Main {
private String name;
private int year;
public Main(String name, int year) {
this.name = name;
this.year = year;
}
protected static Map<Integer, Main> input = new LinkedHashMap<Integer, Main>();
input.put(1, new Main("Chris", 1980);
input.put(2, new Main("Daphne", 1981);
input.put(3, new Main("Sandra", 1976);
input.put(4, new Main("Adele", 1980);
So now what I'd like to be able to do is to list everyone by year. So my expected output would look like this:
1976: Sandra
1980: Chris, Adele
1981: Daphne
Many thanks
One way to do it is to use a stream, for example:
Map<Integer,List<Main>> mainByYear = input.values().stream().collect(Collectors.groupingBy
(e -> e.year));
Then you can iterate through the mainByYear map to print out the key, and the associated list members.
Using streams you can do:
public class Main {
private String name;
private int year;
public Main(String name, int year) {
this.name = name;
this.year = year;
}
public String getName() {
return name;
}
public int getYear() {
return year;
}
public static void main(String[] args) {
Map<Integer, Main> input = new LinkedHashMap<>();
input.put(1, new Main("Chris", 1980));
input.put(2, new Main("Daphne", 1981));
input.put(3, new Main("Sandra", 1976));
input.put(4, new Main("Adele", 1980));
input.entrySet().stream().map(Map.Entry::getValue)
.collect(Collectors.groupingBy(Main::getYear))
.forEach((key, value) -> System.out.println(
key + ": " + String.join(", ", value.stream().map(Main::getName)
.collect(Collectors.toList()))));
}
}
This question already has answers here:
Setter methods or constructors
(10 answers)
Why use getters and setters/accessors?
(37 answers)
Closed 6 years ago.
In the below code I've already declared that room = r; subject = s; and time = t; in the user defined constructor, so why is it necessary to do so again in set methods, my lecturer specifically asked that we add set methods for the room subject and time but it's redundant code as when I comment it out it still works. Do you only need to include set methods when there is no used defined constructor? What could be the advantage of having them set methods there?
class LectureTest{
public static void main (String [] args){
Lecture l1 = new Lecture(140, "Comp", 5);
l1.display();
Lecture l2 = new Lecture(280, "Sports", 3);
l2.display();
Lecture l3 = new Lecture(101, "Business", 5);
l3.display();
Lecture l4 = new Lecture(360, "Shooting", 4);
l4.display();
Lecture l5 = new Lecture();
l5.display();
}
}//end of LectureTest
class Lecture{
private int room;
private String subject;
private int time;
Lecture(int r, String s, int t){
room = r;
subject = s;
time = t;
}
Lecture(){}
public void setroomNumber(int r){
room = r;
}
public void setSubject(String s){
subject = s;
}
public void setTime(int t){
time = t;
}
public int getroomNumber(){
return room;
}
public String getSubject(){
return subject;
}
public int getTime(){
return time;
}
public void display(){
System.out.printf("\n" + "Room Number: " + getroomNumber() + "\n" + "Subject: " + getSubject() + "\n" + "Time " + getTime() + "\n");
}
}
The constructor "initializes" your values.
Let's say you have...
public class Person {
public String name;
public int age;
public Person (String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
String str;
str = "My name is "+name+" and I am "+age+" years old!";
return str;
}
}//End of Person
public class Main {
public static void main(String [] args) {
Person person = new Person("Bob", 15);
System.out.println(person.toString());
System.out.println("Switching my name...");
person.setName("Joe");
System.out.println(person.toString());
}
}//End of main
You see the difference? You should use the constructor if you want to create a new instance of the object. This way, you can set all the fields of the object at once and not need to call 490832490 setters (in this case, one for name and one for age...). You then can use the setter approach when you want to change the value of a field, PRIOR TO the object been created.
I DID ALL THIS ON THIS FORUM SO I MIGHT HAVE SYNTAX ERRORS SO CAREFUL...DIDN'T USE AN IDE IF YOU WANT TO TEST IT
The set methods make your object mutable. If you don't have the set methods and your variables are private then the Object will be immutable. You won't be able to change the values after it is constructed...If the values need to change you would have to create a new Object.
"Setters" allow you to modify private attributes of your object after instantiating. For example:
Lecture l1 = new Lecture(140, "Comp", 5);
//Since "room" is private you can't write l1.room = 4
//and have to use the setter method instead:
l1.setroomNumber(4);
l1.display();
They are also very useful if you want to do something if an attribute changes.
Let's assume you are using Observers, then you could call notifyObservers() or setChanged() in your setter method and never have to worry about these methods not getting called if your attribute changes.
So I'm creating a student database thing for a school project. My first issue is that upon creating a new student I should see "Application number ### has registered successfully". Now the problem is that we have to have that number generate (### referring to the number) sequentially from 1 every time a new application is recorded. How would I go about doing that?
So far this is what there is but I can't seem to get the number to generate incrementally.
public TestApplication(String Surname, String personalIdNo)
{
if (isValidpersonalIdNo(personalIdNo) == true)
{
Student.add(Surname);
Application.put(personalIdNo, Student);
System.out.println("Application number ### " + "has registered successfully");
}
else
{
System.out.println("Application has failed, Personal id: " + personalIdNo);
}
}
Any help with this would be appreicated.
Since you seem to be using lots of static methods, I believe the best thing for you to do in this case is to create a static field called latestId and a static method called generateId, both in the Student class. Then you can call the generateId method whenever you call Student.add.
However, please note that this solution does not work if your application is multithread.
public class Student {
private static int latestId = 0;
public static int generateId() {
return ++latestId;
}
...
}
You can write a singleton class that will produce the ids for you:
class Generator {
private AtomicInteger count = new AtomicInteger(1);
private static Generator generator = new Generator();
private Generator() { }
public static Generator getInstance() {
return generator;
}
public int generate() {
return count.getAndIncrement();
}
}
Now, when you need to get a new id, you just call the generate method. The AtomicInteger is used because you might need the id from multiple threads and it will make the concurrent access safe.
The singleton Generator provides a single entry point to the id-generating facility.
You can use your storage type to give you the amount of added students that were put into DB.
I don't know what type you use to store your students. If it is hashmap or vector you can use size method to print students count. So I assume if you have Application.put you probably have a field in your Application type that is used to store each student. Then you can add a method like getStudentsCount to it and you should be all set. Since I don't know much about your Application type the above is all assumptions. Below you can find how I would solve that:
import java.util.HashMap;
import java.util.Vector;
class Student{
private String name;
private int personalID;
public Student(String name, int personalID){
this.name = name;
this.personalID = personalID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPersonalID() {
return personalID;
}
public void setPersonalID(int personalID) {
this.personalID = personalID;
}
}
class DB{
private HashMap<Integer, Student> students = new HashMap<Integer, Student>();
public boolean addStudent(Student student) {
Integer studentId = new Integer(student.getPersonalID());
if( !students.containsKey(studentId)){
students.put(new Integer(studentId), student);
return true;
}
else
return false;
}
public int getStudentCount() {
return students.size();
}
}
class Operations{
DB db;
public Operations(DB db){
this.db = db;
}
public boolean addStudent(String name, int personalID){
Student student = new Student(name, personalID);
return db.addStudent( student );
}
}
public class SimpleStudentDB {
public static void main(String [] args){
DB db = new DB();
Operations operations = new Operations(db);
if( operations.addStudent( "Jason", db.getStudentCount()+1) )
System.out.println("Student added successfully. DB contains ###"+db.getStudentCount()+" elements");
else
System.out.println("Operation failed");
}
}