How to print out planes by airline - java

Hey im using a hashmap of string and flights to create a flight store called planeStore. So then i made another store(Airline store) also using a hashmap. I put the planeStore into the AirlineStore. But i cant get the airlines printing out with the planes.
I thought by putting string airlineName into Airlines constrcutor. And passing in "Plane Name" When creating Airline airline = new Airline("PlaneName"); that this would work but it hasnt.
here is my code:
Airline
import java.util.HashMap;
public class Airline
{
private String airlineName;
private HashMap<String, PlaneStore> map;
public Airline(String airlineName)
{
this.airlineName = "";
map = new HashMap<String, PlaneStore>();
}
public void add(PlaneStore plane)
{
map.put(airlineName, plane);
}
public void remove(String flight)
{
map.remove(flight);
}
public void printPlane()
{
System.out.println("\n********Flight List********");
for (PlaneStore plane: map.values()) {
//System.out.println(plane);
// class
// or:
System.out.println(airlineName);
System.out.println(plane.toString());
}
}
}
plane.toString is the toString of the PlaneStore:
public String toString() {
return "PlaneStore [airlineName=" + airlineName + ", planeMap="
+ planeMap + "]";
}
MainApp
import java.util.Scanner;
public class MainApp
{
private Scanner keyboard = new Scanner(System.in);
public static void main(String[] args)
{
new MainApp().start();
}
public void start()
{
Airline airline1 = new Airline("AerLingus");
Airline airline2 = new Airline("Ryan Air");
PlaneStore planeStore = new PlaneStore("Aer Lingus");
PlaneStore planeStore2 = new PlaneStore("Ryan Air");
Flight p1 = new Flight("Aer Lingus","A01", 150.5, 10.5, 500, Flight.AIRPLANETYPE.AIRBUS);
Flight p2 = new Flight("Aer Lingus","B01", 50.3, 1.5, 91, Flight.AIRPLANETYPE.CORPORATE);
Flight p3 = new Flight("Aer Lingus","C01", 12.2, -3.1, 56, Flight.AIRPLANETYPE.AIRBUS);
Flight p4 = new Flight("Ryan Air","D01", 10.5, 1.5, 430, Flight.AIRPLANETYPE.PRIVATE);
Flight p5 = new Flight("Ryan Air","E01", 0.3, 2.1, 101, Flight.AIRPLANETYPE.CORPORATE);
Flight p6 = new Flight("Ryan Air","F01", 2.2, -3, 291, Flight.AIRPLANETYPE.AIRBUS);
planeStore.add(p1);
planeStore.add(p2);
planeStore.add(p3);
planeStore.print();
airline1.add(planeStore);
airline1.add(planeStore);
airline1.add(planeStore);
airline1.printPlane();
planeStore2.add(p4);
planeStore2.add(p5);
planeStore2.add(p6);
airline2.add(planeStore2);
airline2.add(planeStore2);
airline2.add(planeStore2);
airline2.printPlane();
}
}

Your Airline construtor receives a String argument but you are not assignment the instance variable airlineName of the class Airline to this argument. You are just making airlineName set to "".
public Airline(String airlineName)
{
this.airlineName = "";
map = new HashMap<String, PlaneStore>();
}
you mean:
public Airline(String airlineName)
{
this.airlineName = airlineName;
map = new HashMap<String, PlaneStore>();
}
Looking further in your code, it appears that each Airline class will have an map but you only add a key to this map, along with the values PlaneStore. So it appears that you will never have two or more keys for each map on each Airline class. Therefore, there is no point in using map, you can use instead an ArrayList.
If I understand correctly your objective you can simplify your AirLine class to something like this:
public class Airline
{
private String airlineName; // Name of the company
private ArrayList <PlaneStore> planeStore;
public Airline(String airlineName)
{
this.airlineName = airlineName;
map = new ArrayList<PlaneStore>();
}
public void add(PlaneStore plane){ planeStore.add(plane);}
public void printPlane()
{
System.out.println(airlineName);
System.out.println("\n********Flight List********");
for (PlaneStore plane: planeStore)
{
System.out.println(plane.toString());
}
}
}

You're setting airlineName to "" rather than the String that you pass into it throught the constructor.

Once you change the code to read this.airlineName = airlineName; you should be ok with this part.
By the way it still looks like you are using the same key for every plane you add. This will constantly overwrite the last plane you added with the new one. If you want to be able to print out all of the planes, you need to give them each a unique key. Otherwise this won't work.

Related

Sorting an array of classes based only on field name

I have an application where a user provides me with the name of a field, e.g name or costInCents, and I have to sort by that field. I have ways of guaranteeing that the field name will be correct. This application causes the complication that I simply cannot make my class Comparable and implement a specific compareTo(), since with a custom implementation of compareTo() I need to know which fields / methods to use at implementation time.
So to achieve this goal, I am trying to use reflection in order to match the field to its accessor. Here's a MWE of what I want to do.
Class Product is a simple POJO class whose instances I want to pairwise compare:
public class Product
{
final String name;
final Integer quantity;
final Long costInCents;
public Product(final String name, final Integer quantity, final Long costInCents)
{
this.name = name;
this.quantity = quantity;
this.costInCents = costInCents;
}
public String getName()
{
return name;
}
public Integer getQuantity()
{
return quantity;
}
public Long getCostInCents()
{
return costInCents;
}
}
And my Main class, which is currently incomplete:
public class Main {
public static void main(String[] args) {
final Product[] productArray =
{
new Product("Clorox wipes", 50, 700L),
new Product("Desk chair", 10, 12000L),
new Product("TV", 5, 30000L),
new Product("Bookcase", 5, 12000L),
new Product("Water bottle", 20, 700L),
};
// The following void methods are supposed to sort in-place with something like Arrays.sort() or Collections.sort(),
// but I am also open to solutions involving stuff like Stream::sorted() or similar ones, which return a sorted array.
sortByField(productArray, "costInCents");
sortByField(productArray, "name");
}
private void sortByField(final Product[] productArray, final String sorterFieldName)
{
final Field sorterField = getSorterField(sorterFieldName, LiteProduct.class); // Gets the Field somehow
final Method sorterAccessor = getSorterAccessor(sorterField, LiteProduct.class); // Given the Field, this is easy
Arrays.sort((Product p1, Product p2)->((Comparable<?>)sorterAccessor.invoke(p1)).compareTo(sorterAccessor.invoke(p2)) > 0); // Capture of ? instead of Object
}
}
Unfortunately, the Arrays.sort() line results in a compile-time error with message Capture of ? instead of Object. I have tried casting the second argument to Comparable<?>, Comparable<? super sorterField.getType(), etc, with no luck. Ideas?
Possibly the best way - with sorting strategies. No need for reflection, compatible with more complex sorting logic:
Map<String, Comparator<Product>> sortingStrategies = new HashMap<>(){
{
put("costInCents", Comparator.comparingLong(p->p.costInCents));
put("quantity", Comparator.comparingLong(p->p.quantity));
put("name", Comparator.comparing(p->p.name));
}
};
private void sortByField(final Product[] productArray, final String sorterFieldName)
{
Arrays.sort(productArray, sortingStrategies.get(sorterFieldName));
}
You could write a Comparator for each field and use it by name via a Map:
public class Product
{
private final static Map<String,Comparator<Product>> COMPARATORS;
static {
COMPARATORS = new HashMap<>();
COMPARATORS.put("name", new NameComparator());
COMPARATORS.put("costInCents", new CostInCentsComparator());
}
final String name;
final Integer quantity;
final Long costInCents;
public Product(final String name, final Integer quantity, final Long costInCents)
{
this.name = name;
this.quantity = quantity;
this.costInCents = costInCents;
}
public String getName()
{
return name;
}
public Integer getQuantity()
{
return quantity;
}
public Long getCostInCents()
{
return costInCents;
}
static class NameComparator implements Comparator<Product> {
#Override
public int compare(Product o1, Product o2) {
return o1.getName().compareTo(o2.getName());
}
}
static class CostInCentsComparator implements Comparator<Product> {
#Override
public int compare(Product o1, Product o2) {
return o1.getCostInCents().compareTo(o2.getCostInCents());
}
}
static Comparator<Product> getComparator(String name) {
return COMPARATORS.get(name);
}
}
and use that in the main class
public class Main {
public static void main(String[] args) {
final Product[] productArray =
{
new Product("Clorox wipes", 50, 700L),
new Product("Desk chair", 10, 12000L),
new Product("TV", 5, 30000L),
new Product("Bookcase", 5, 12000L),
new Product("Water bottle", 20, 700L),
};
// The following void methods are supposed to sort in-place with something like Arrays.sort() or Collections.sort(),
// but I am also open to solutions involving stuff like Stream::sorted() or similar ones, which return a sorted array.
sortByField(productArray, "costInCents");
sortByField(productArray, "name");
}
private static void sortByField(final Product[] productArray, final String sorterFieldName)
{
Arrays.sort(productArray, Product.getComparator(sorterFieldName));
}
}
You may have to do minor changes like makeing it null safe or something
you can try this:
public class Test{
public static void main(String arg[]){
final Product[] productArray =
{
new Product("Clorox wipes", 50, 700L),
new Product("Desk chair", 10, 12000L),
new Product("TV", 5, 30000L),
new Product("Bookcase", 5, 12000L),
new Product("Water bottle", 20, 700L),
};
Arrays.sort(productArray,(p1, p2) -> p1.getName().compareTo(p2.getName()));
for(Product p: productArray){
System.out.println(p.getName());
}
}
}
in this case Comparator is a functional interface so I used lambad expression. but you can do this too

Looking through class Arraylist objects without nested loops

I had this object oriented programming project last semester and it was all about simulating a simple dormitory.
1.There should have been a manager class in which the main method and like 80 percent of the other methods had to be there.
2.A dormitory class containing an arraylist of blocks.
3.A block class containing an arraylist of rooms.
4.A room class containing an arraylist of students.
5.All of these classes contained getters and setters for their private variables.
There were a few methods that we should've added to the program which has nothing to do with my question,so I will not write them in here,but the thing is,a few of theses methods needed to look through these arraylists to find a specific object.For example,a student with a specific student number.I created these methods with nested loops.But I know there is some way I could avoid heavy nesting.
Here is my reduced code.I will only let the manager class contain one nested loop method as an example:
import java.util.Scanner;
public class Manager {
private String name;
private String familyName;
private String userName;
private String passWord;
private static Scanner scan = new Scanner(System.in);
private Dormitory dorm = new Dormitory();
private static Menu menu = new Menu();
private Student tempStudent;
private Block tempBlock;
private Room room;
private boolean bool;
{
dorm.setDormManager(this);
}
public Manager(String managerName, String managerID) {
name = managerName;
userName = managerID;
}
//find student with its number
public void findStudent() {
//Taking the student number from the user.
System.out.println("Please enter the student number:");
String studentNum = scan.nextLine();
for (int i = 0; i < dorm.getBlockList().size(); i++)
for (int j = 0; j < dorm.getBlockList().get(i).getRooms().size(); j++)
for (int k = 0; k < dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().size(); k++)
if (dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k).getStudentNumber().equals(studentNum)) {
tempStudent = dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k);
break;
}
}
public void create() {
//Used loops for the original program.
Block block1 = new Block("1");
Block block2 = new Block("2");
dorm.getBlockList().add(block1);
dorm.getBlockList().add(block2);
Room room1 = new Room("1");
Room room2 = new Room("2");
dorm.getBlockList().get(0).getRooms().add(room1);
dorm.getBlockList().get(1).getRooms().add(room2);
Student student1 = new Student("12345678");
Student student2 = new Student("98765432");
dorm.getBlockList().get(0).getRooms().get(0).getRoomStudents().add(student1);
dorm.getBlockList().get(1).getRooms().get(0).getRoomStudents().add(student2);
}
public static void main(String[] args) {
Manager manager = new Manager("Dumbledore", "#1112");
manager.create();
}
}
public class Dormitory {
private int blocks;
private Manager dormManager;
private long allMembers;
private ArrayList<Block> blockList = new ArrayList<Block>();
}
public class Block {
private String blockNumber;
private ArrayList<Room> rooms = new ArrayList<Room>();
private Dormitory dorm = new Dormitory();
public Block(String blockNum) {
blockNumber = blockNum;
}
}
public class Room {
private String roomNumber;
private ArrayList<Student> roomStudents = new ArrayList<Student>();
private Block roomBlock;
private Student roomManager;
public Room(String roomNum) {
roomNumber = roomNum;
}
}
public class Student {
private String studentName;
private String studentFamilyName;
private String studentNumber;
private Room room;
public Student(String studentNum) { //Creates a student object using the student number.
studentNumber = studentNum;
}
}
I tried my best to reduce the code.
I searched a lot and asked a lot of people about this but I didn't get my desired answer.I'm not sure why I couldn't find anything about this,but I'd really appreciate it if you'd lend me a hand or give me the link of a related article.
Short answer: No, you should never loop through everything checking for getStudentNumber().equals(studentNum). This has linear time complexity O(N)
Long answer: You should index your data based on your queries
Eg: Indexing with HashMaps which have constant time complexity O(1). (Note: This code is not thread safe)
public class SchoolService {
private Map<String, Student> studentsById = new HashMap<>();
private Map<Long, Dorm> dormsById = new HashMap<>();
/// dormsByAreaCode is showing an example of an index which groups objects into lists
private Map<String, List<Dorm>> dormsByAreaCode = new HashMap<>();
public void addStudent(Student student) {
if (studentsById.containsKey(student.getName()) {
throw new IllegalStateException("Duplicate student " + student.getName());
}
studentsById.put(student.getId(), student);
}
public Student getStudentById(String studentId) {
Student student = studentsById.get(studentId);
if (student == null) {
throw new IllegalStateException("No such student " + studentId);
}
return student;
}
public void addDorm(Dorm dorm) {
// TODO: validation
dormsById.put(dorm.getId(), dorm);
List<Dorm> areaDorms = dormsByAreaCode.get(dorm.getAreaCode());
if (areaDorms == null) {
areaDorms = new ArrayList<>();
dormsByAreaCode.put(dorm.getAreaCode(), areaDorms);
}
areaDorms.add(dorm);
}
public Dorm getDormById(long dormId) {
Dorm dorm = dormsById.get(id);
// TODO: validation
return dorm;
}
public List<Dorm> getDormsByAreaCode(String areaCode) {
List<Dorm> areaDorms = dormsByAreaCode.get(areaCode);
// TODO: validation
return areaDorms;
}
// etc
}
The following quote is from tutorialspoint. This is the perfect use case of the forEach method from the Stream interface. The link I provided and further reading on Streams can help avoid repetitive code.
Using collections framework in Java, a developer has to use loops and make repeated checks. Another concern is efficiency; as multi-core processors are available at ease, a Java developer has to write parallel code processing that can be pretty error-prone.
dorm.getBlockList().stream().forEach((b) -> {
b.getRooms().stream().forEach((r) -> {
...
})
});
You can also read about parallelStreams from here.

How do I add an element to an array thats in a different class in Java

so I have this array in a class called Park:
private Product[] stock = new Product[MAX_PROD];
In another class called Test(I have Park extended to test), I have these elements that I trying to add to the array, but it never works. This is how it looks:
These are the variables for sedan "public Sedan(double price, int quantity, String make, String model, int year, String
color)"
public class AutoParkInventoryTestProgram {
public static void main(String[] args) {
AutoPark park1 = createPark1();
System.out.println(park1.getName() + "'s Stock Is:");
park1.displayAllProducts();
System.out.println();
}
public static AutoPark createPark1() {
AutoPark park1 = new AutoPark("Carleton AutoPark");
Sedan s1 = new Sedan(100, 10, "Ford", "Model-1", 2018, "White");
Sedan s2 = new Sedan(200, 10, "Honda", "Model-2", 2019, "Red");
park1.addProduct(s1);
park1.addProduct(s2);
return park1;
Sedan is a different class btw.
This is one of the red errors I get before I run my code:
Required type:
Product
Provided:
Sedan
Sorry for the lack of information I gave initially, this is how addProduct looks:
public boolean addProduct(Product p) {
if (currentStock < MAX_PROD - 1) {
stock[currentStock++] = p;
return true;
}
return false;
}

Cant get java stream to work with arraylist

So, I have been playing around with java streams a bit, and found something very frustrating.
I want to make a list of this type of object (Customer), and after that use a stream to filter out all those objects where glad == false.
package com.company;
public class Customer {
public String name;
public int points;
public boolean glad;
public Customer(String name, int points, boolean glad) {
this.name = name;
this.points = points;
this.glad = glad;
}
public boolean isGlad() {
return this.glad;
}
}
Whenever I try doing it with a regular array, everything seems to work just fine:
Customer kunde1 = new Customer("jens", 20, true);
Customer kunde2 = new Customer("marie", 20, false);
Customer kunde3 = new Customer("niels", 20, false);
Customer kunde4 = new Customer("jens", 20, true);
Customer kunde5 = new Customer("jens", 20, true);
Customer[] kunderne = {kunde1,kunde2,kunde3,kunde4,kunde5};
Customer[] filtered = Stream.of(kunderne)
.filter(Customer::isGlad)
.toArray(Customer[]::new);
But whenever I try to create the stream from something other than an array, like an ArrayList, I am not able to access the object attributes within my lambda statement
ArrayList<Customer> customers = new ArrayList<>();
Customer kunde1 = new Customer("jens", 20, true);
Customer kunde2 = new Customer("marie", 20, false);
Customer kunde3 = new Customer("niels", 20, false);
Customer kunde4 = new Customer("jens", 20, true);
Customer kunde5 = new Customer("jens", 20, true);
customers.add(kunde1);
customers.add(kunde2);
customers.add(kunde3);
customers.add(kunde4);
customers.add(kunde5);
Customer[] filtered = Stream.of(kunderne)
.filter(Customer::isGlad)
.toArray(Customer[]::new);
But this code won't even run. Why does this happen, and why does it only seem to work with arrays?
There is no such a method as Stream.of(List<T>).
You should use cusomters.stream() which will convert your list into the stream.
That's happening because Stream.of(cusomters) is creating the one element Stream with the ArrayList object inside - obviously there is not method
public static boolean isGlad(ArrayList<Customer> customers) {
return false;
}
and this is why the code is not running
When you are passing Customer[] object to the Stream.of instead of of method version
public static<T> Stream<T> of(T t)
overloaded
public static<T> Stream<T> of(T... values)
is being used and everything is fine
Here is what you wanted to do.
Customer[] filtered = Stream.of(kunderne).filter(Customer::isGlad).map(
cust -> new Customer(cust.name, cust.points, cust.glad)).toArray(
Customer[]::new);
for (Customer c : filtered) {
System.out.println(c.name + " " + c.points + " " + c.glad);
}
You needed to map the filtered customer to a new customer and then put those in an array. Another option would be to add a constructor that takes an existing customer and uses that as input. Here is how that would work.
Customer[] filtered = Stream.of(kunderne).filter(Customer::isGlad).map(
Customer::new).toArray(Customer[]::new);
for (Customer c : filtered) {
System.out.println(c.name + " " + c.points + " " + c.glad);
}
// modified customer class with additional constructor
class Customer {
public String name;
public int points;
public boolean glad;
public Customer(String name, int points, boolean glad) {
this.name = name;
this.points = points;
this.glad = glad;
}
public Customer(Customer cust) {
this(cust.name, cust.points, cust.glad);
}
public boolean isGlad() {
return this.glad;
}
}

ArrayList is empty when called in seperate class Java

I have class which initiates an arraylist of type String. I then add some dummy data into this array.
public class Main {
public static void main(String[] args)
{
Home h = new Home();
h.add();
}
}
public class Home
{
public ArrayList<String> Group_Customers= new ArrayList<String>();
public void add()
{
String[] group1 = {"0", "Mr", "Smith", "Andrew"}
for(int i = 1; i < group1.length; i++)
{
Group_Customers.add(group1[i]);
}
Add_Booking a = new Add_Booking();
a.Add();
}
}
In a seperate class. I then call this arraylist and add more data to it. However the array is empty in this different class
public class Add_Booking
{
String Title;
String Firstname;
String Surname;
public void add_Data
{
Title = "Mr";
Firstname = "Bob";
Surname = "Gallow";
save_Data();
}
public void save_Data
{
Home h = new Home();
String[] responses = {Title, Firstname, Surname};
for(int i = 1; i < responses.length; i++)
{
h.Group_Customers.add(responses[i]);
}
System.out.println(h.Group_Customers);
}
}
--Outputs responses without group1 test from class Home.
Am I refering to Group_Customers wrong within this different class?
All help appreciated.
Thanks
When calling Home h = new Home(); you instantiate a new Home with the default constructor.
Make sure you add the dummy data in the constructor if you want the array to contains data. Also, the actual code would not compile, you can't just throw method call in class body.
You would have something like this :
public class Home
{
//Declare the List
public ArrayList<String> Group_Customers = null;
//Default constructor
public Home()
{
//Instantiate and add dummy data
Group_Customers = new ArrayList<String>();
Group_Customers.add("test");
}
}
public class Add_Booking
{
public static void main(String args[])
{
//Construct a new home with default constructor.
Home h = new Home();
//Add new data
h.Group_Customers.add("new data");
//Display List content (should display test and new data)
System.out.println(h.Group_Customers);
}
}
Note that by convention, variable should start with a lower-case and an upper-case at each words so you should rename your variable as groupCustomers.

Categories

Resources