It could be a very simple solution but I just started learning Java. I would like to add every instantiated Product to the productList. Is there any way to solve this problem without modifying the access modifiers?
public class Product {
private int id;
private String name;
private float defaultPrice;
private Currency defaultCurrency;
private Supplier supplier;
private static List<Product> productList;
private ProductCategory productCategory;
public Product(float defaultPrice, Currency defaultCurrency, String name) {
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
}
}
You can just add a newly created Product to the list in its constructor:
public class Product {
private int id;
private String name;
private float defaultPrice;
private Currency defaultCurrency;
private Supplier supplier;
private static List<Product> productList = new LinkedList<>();
private ProductCategory productCategory;
public Product(float defaultPrice, Currency defaultCurrency, String name){
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
productList.add(this);
}
}
Change the initialisation line
private static List<Product> productList;
to
private static List<Product> productList = new LinkedList<>();
Add productList.add(this) as the last line of the constructor.
So each time you call the Product constructor, it will add this instance to the static list.
Like Peter Lawrey mentionned it in the comment section of Mureinik's answer, having a static collection in the POJO is not the best solution.
I would suggest to use a simple facade. This limit the list existence to the facade life and don't include the logic of a collection in a POJO.
public class FacadeProduct {
private List<Product> cacheProduct = new ArrayList<>();
public Product createProduct(float defaultPrice, Currency defaultCurrency, String name){
Product p = new Product(defaultPrice, defaultCurrency, name);
cacheProduct.add(p);
return p;
}
}
This would be quite simple to use.
public static void main(String ars[]){
{
FacadeProduct f = new FacadeProduct();
{
Product p1 = f.createProduct(1f, null, "test1");
Product p2 = f.createProduct(1f, null, "test2");
Product p3 = f.createProduct(1f, null, "test3");
// Here, the list have 3 instances in it
}
// We lose the p1, p2, p3 reference, but the list is still holding them with f.
}
//Here, we lose the f reference, the instances are all susceptible to be collected by the GC. Cleaning the memory
}
Initialize productList with null, and then modify the constructor as follows:
public Product(float defaultPrice, Currency defaultCurrency, String name) {
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
if (productList == null) productList = new ArrayList<>();
productList.add(this);
}
Related
i have an exercise which i must write a programm in which i manage the timetable of trains.I write all the programm put i can not write the main class, because i must make an Arraylist with 3 passengers and i dont know what i must put in the blank
Code:
public class Route {
private int id;
private int aeroplane;
private String departure;
private String arrival;
private ArrayList<Ticket> Tickets = new ArrayList<>() ;
public Route(){
id = 0 ;
aeroplane = 0 ;
departure = " ";
arrival = " ";
Tickets = new ArrayList<>();
}
public Route(int ID, int aerop, String depar,String arriv,ArrayList<Ticket> tick ){
id=ID;
aeroplane=aerop;
departure=depar;
arrival=arriv;
Tickets=tick;
}
public static void main(String[] args) {
ArrayList <Train> train=new ArrayList<>();
Route d1= new Route(0051,50,"Greece","Italy",);// what i have to write in the last blank?
}}
I suppose you have those three classes:
Train
Ticket - which is valid for multiple trains
Route - which could contain multiple Tickets
Then you should model your Route like that:
public class Route {
private final int id;
private final int aeroplane;
private final String departure;
private final String arrival;
private final List<Ticket> tickets;
public Route(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets) {
this.id = id;
this.aeroplane = aeroplane;
this.departure = departure;
this.arrival = arrival;
this.tickets = tickets;
}
}
Your route class does not have, and should not have a list of lists of trains. It is perfectly fine, that you have it has a list of tickets.
To the question of how to add the list of Trains to the Route instantiation, you should create a ticket first, or multiple if you like.
public static void main(String[] args) {
// create trains
Train train1 = new Train(1202, "Piraeus", "Athens");
Train train2 = new Train(1302, "Athens", "Thessaloniki");
Train train3 = new Train(1502, "Thessaloniki", "Rome");
// create ticket(s)
Ticket ticket = new Ticket(95, List.of(train1, train2, train3));
// create route and pass tickets
Route myRoute = new Route(0051, 50, "Greece", "Italy", List.of(ticket));
}
To create the lists here I used the factory method java.util.List.of (available since Java 9). Your route class is also a good candidate for a record (since Java 18). As an record it would look like:
public record RouteRecord(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets) {}
Also, think about the concept of immutability.
In your main method ( it's not a class ) :
List<Ticket> tickets = new ArrayList<>();
tickets.add( new Ticket());
Route d1 = new Route(0051,50,"Greece","Italy",tickets);
and as it was mentined before you need to define a constructor :
public Route(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets ){
this.id = id;
this.aeroplane = aeroplane;
this.departure = departure;
this.arrival = arrival;
this.Tickets = tickets;
}
I have a test class called LibraryTest. The junit test defined in this class is failing. I want to pass the failing junit test by only modifying my source code and without changing anything in the junit test.
I have the class files Book.java
public class Book {
private int id;
private final String name;
private final String description;
private final Category category;
public Book(int id, String name, String description, Category category) {
super();
this.id = id;
this.name = name;
this.description = description;
this.category = category;
}
public enum Category {
CoreJava,
Electronics,
Python,
Hibernate
}
// getter and setters too are there
}
and Library.java
public class Library {
private final Set<Book> books = new HashSet<Book>();
public boolean addBook(final Book book) {
return books.add(book);
}
public Iterator<Book> getBooks() {
return books.iterator();
}
}
The test class file LibraryTest.java is as follows. The junit test canSortLibrary() is failing.
public class LibraryTest{
private Library library;
private Book hibernate1 ;
private Book hibernate2 ;
private Book coreJava ;
private Book electronics ;
private Book python;
#Before
public void setUp() {
library = new Library();
hibernate1 = new Book(0, "hibernate1", "hibernate book1", Category.Hibernate);
hibernate2 = new Book(0, "hibernate2", "hibernate book2", Category.Hibernate);
coreJava = new Book(0, "coreJava", "written by x", Category.CoreJava);
electronics = new Book(0, "electronics", "written by y", Category.Electronics);
python = new Book(0, "Python Book", "written by someone", Category.Python);
library.addBook(hibernate1);
library.addBook(hibernate2);
library.addBook(coreJava);
library.addBook(electronics);
library.addBook(python);
}
#Test
public void canSortLibrary() throws Exception {
final Book[] orderedBooks = new Book[] { coreJava, hibernate1, hibernate2, electronics, python};
int i = 0;
final Iterator<Book> books= library.getBooks();
while (books.hasNext()) {
final Book book = books.next();
Assert.assertTrue(book == orderedBooks[i++]);
}
}
}
According your constraints you need to make your Book class comparable in a very particular way.
Book.java
import java.util.Arrays;
public class Book implements Comparable<Book> {
static String specialOrder[] = {"coreJava", "hibernate1", "hibernate2", "electronics", "Python Book"};
private int id;
private final String name;
private final String description;
private final Category category;
public Book(int id, String name, String description, Category category) {
super();
this.id = id;
this.name = name;
this.description = description;
this.category = category;
}
public enum Category {
CoreJava, Electronics, Python, Hibernate
}
#Override
public int compareTo(Book otherBook) {
int index = Arrays.asList(specialOrder).indexOf(name);
int indexOther = Arrays.asList(specialOrder).indexOf(otherBook.getName());
if (index != -1 && indexOther != -1) {
// both book titles are in the special order array
// the indices indicate their order
return Integer.compare(index, indexOther);
}
// at least one book title is not in the special array
// therefore use natural order of String
return name.compareTo(otherBook.getName());
}
// getter and setters too are there
String getName(){return name;}
}
And use a container which maintains the order:
Library.java
import java.util.*;
public class Library {
private final SortedSet<Book> books = new TreeSet<Book>();
public boolean addBook(final Book book) {
return books.add(book);
}
public Iterator<Book> getBooks() {
return books.iterator();
}
}
Now we are set and here we go:
$ javac Book.java Library.java
$ javac -cp .:junit-4.13.2.jar LibraryTest.java
$ java -cp .:junit-4.13.2.jar:hamcrest-all-1.3.jar org.junit.runner.JUnitCore LibraryTest
JUnit version 4.13.2
.
Time: 0,003
OK (1 test)
$
Here's MVCE: https://github.com/neo4j-examples/movies-java-spring-data-neo4j
If you change one test to:
#Test
public void testFindByTitle() {
String title = "The Matrix";
Movie result = movieRepository.findByTitle(title);
Person p = personRepository.findByName("Keanu Reeves");
assertNotNull(result);
assertEquals(1999, result.getReleased());
}
You can see in debug mode that object p does not have any movies.
Person entity is:
#NodeEntity
public class Person {
#Id
#GeneratedValue
private Long id;
private String name;
private int born;
#Relationship(type = "ACTED_IN")
private List<Movie> movies = new ArrayList<>();
public Person() {
}
public Person(String name, int born) {
this.name = name;
this.born = born;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getBorn() {
return born;
}
public List<Movie> getMovies() {
return movies;
}
}
This is offical example from neo4j. How can i store entity Person with movies in database and also have Movie entity with roles ?
Edit: What i can do is add in Person entity method:
public void addMovie(Movie movie) {
if (this.movies == null) {
this.movies = new ArrayList<>();
}
this.movies.add(movie);
}
And in the test add:
p.addMovie(matrix);
personRepository.save(p);
But i don't like this - cause i setting it manually from two sites.
You do not need to set the references manually from two sides. Expand your code snippet slightly by a single line movie.setPerson(this); and you are done:
public void addMovie(#NotNull Movie movie) {
if (this.movies == null)
this.movies = new ArrayList<>();
this.movies.add(movie);
movie.setPerson(this);
}
Related to my previous thread, i want to print an output like this:
bookId = "1234" (String)
bookName = "Machine Learning" (String)
price = $20 (int)
ratings = (array of object)
rater = a, score = 5
rater = b, score = 3
But this time, i tried to use an OOP manner.
So first, i made a POJO class called ProductView, the class will be look like this:
public class ProductView {
// field
private String bookId;
private String bookName;
private int price;
private List<Ratings> ratings;
// a constructor i tried to make
public ProductView(String bookId, String bookName, int price, List<Ratings> ratings) {
this.bookId = bookId;
this.bookName = bookName;
this.price = price;
this.ratings = ratings;
}
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.itemId = itemId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Ratings getRatings() {
return ratings;
}
public void setRatings(Ratings ratings) {
this.ratings = ratings;
}
}
After that, i made a class called Ratings with the following field:
public class Ratings {
private String rater;
private int score;
public Ratings(String rater, int score) {
this.rater = rater;
this.score = score;
}
}
And finally, i made a Main Class called Main:
public class Main {
public static void main(String[] args) {
}
}
In the Main Class, i want to create an instance of the ProductView class and give it some value.
But i don't know how to do it with a list object param in my constructor.
Anyone can give me some insight?
first:
List is an interface, you should pass an implementation of list such as ArrayList or similar
second:
you have a compilation error in ProductView -> SetBookId, in this.itemId you don't have itemId as member or constructor parameter
furthermore, in get/set rating you need to pass and return list of Ratings.
nameing:
Ratings is actually just a Rating, you can make a new class of List or just use the Rating as is but change the name
now for your Question:
you can initialize first the list with objects and then send it to the constructor
such as:
List<Ratings> ratings = new ArrayList<>();
ratings.add(new Ratings("rater",5));
ratings.add(new Ratings("rater2",6));
ProductView productView = new ProductView("bookId","bookName",1,ratings);
Or, just initialize the ArrayList in the Constructor, the first way is preferable:
ProductView productView1 = new ProductView("bookId","bookName",1,
new ArrayList<Ratings>(Arrays.asList(new Ratings("rater",5), new Ratings("rater2",6))
));
hopefully, this answers your question
same as DodgyCodeException mentioned in the comments.
Is it possible to store three string values added into an array (studentName), and store that into a different array so it can be found later?
Basically my main goal is to store a name, user id, and a balance (fullName, idName, 300).
And add that into a "super(?)" array so when people type down, it finds the fullName and pulls the information from there.
You can create a class
public class Student {
private String name;
private String id;
private int balance;
}
and then you can create a list of these objects:
List<Student> list = new ArrayList<Student>();
Map<String, String> map = new HashMap<String, String>();
then:
List<Map<String, String>> listOfMaps = new ArrayList<Map<String, String>>();
and then:
map.put("name", "Thomas");
map.put("id", "Thomas id");
map.put("balance", ""300);
listOfMaps.add(map);
Anyhow, be careful. You will have to keep numbers (f.e. balance) as a String and after you will need to map it.
Well, I believe you are talking about something like Jagged Array which is available in C# but for java, we can do it in some other ways... like creating a class and manipulating it as Generic List implementation...
public class Student {
private String name;
private int id;
private int balanace;
public Student(){}
public Student(String name, int id, int balance){
this.name = name;
this.id = id;
this.balanace = balance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBalanace() {
return balanace;
}
public void setBalanace(int balanace) {
this.balanace = balanace;
}
}
In some other class where you would want to manipulate
public class ManipulateData {
public static void main(String[] args){
Student student1 = new Student("James", 1, 500);
List<Student> list = new ArrayList<Student>();
list.add(student1);
for(Student s: list){
System.out.println("Name : " + s.getName());
System.out.println("ID : " + s.getId());
System.out.println("Balance : " + s.getBalanace());
}
}
}