How do I create a list of generic list? I have a Boxcar class that takes a generic argument and a Train class that is supposed to create a list of Boxcars. We are supposed to specify the type that will be in Boxcar in a separate main class, so until then boxcar has to stay generic. The following is the code that I have written. It compiles but in a separate driver class when calling the load method I get the error The method load(capture#1-of ?) in the type Boxcar<capture#1-of ?> is not applicable for the arguments (Person)
package proj5;
import java.util.ArrayList;
import java.util.List;
public class Train {
private List<Boxcar<?>> train;
private int maxSpeed;
private int minSpeed;
private String position;
private int numBoxcars;
private int maxNumBoxcars;
private int speed;
private String destination;
private boolean stopped = true;
public Train(int maxSpeed, int minSpeed, int maxNumBoxcars, String position){
train = new ArrayList<Boxcar<?>>();
this.maxSpeed = maxSpeed;
this.minSpeed = minSpeed;
this.maxNumBoxcars = maxNumBoxcars;
this.position = position;
}
public int getMaxNumBoxcars(){
return maxNumBoxcars;
}
public int getSpeed(){
return speed;
}
public String getPosition(){
return position;
}
public int getMaxSpeed(){
return maxSpeed;
}
public int getNumBoxcars(){
return numBoxcars;
}
public List<Boxcar<?>> getTrain(){
return train;
}
public void depart(String destination){
this.destination = destination;
speed = minSpeed;
stopped = false;
}
public void arrive(){
stopped = true;
position = destination;
}
public void addCar(Boxcar<?> boxcar, int i){
if(stopped){
boxcar.setMaxItems(i);
train.add(boxcar);
}
}
public void removeCar(int i){
if(stopped){
train.remove(i);
}
}
}
package proj5;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class Boxcar<T extends Comparable<T>> {
private List<T> boxcar;
private int maxItems;
public Boxcar(){
boxcar = new ArrayList<T>();
}
public void load(T thing){
if(!boxcar.contains(thing) && boxcar.size() < maxItems){
boxcar.add(thing);
Collections.sort(boxcar);
}else{
}
}
public int getMaxItems(){
return maxItems;
}
public void setMaxItems(int i){
maxItems = i;
}
public void unload(T thing){
boxcar.remove(thing);
}
public List<T> getBoxcar(){
return boxcar;
}
}
I hope this better conveys what I am trying to accomplish
BoxCar which is a generic class:
class BoxCar<T>{
}
Train class which has a list of Boxcar:
class Train {
List<BoxCar<PassTheTypeHere>> = new ArrayList<BoxCar<PassTheTypeHere>>();
}
You need to supply a type in place of T and ? when creating a Generic List. For example a List of Boxcars containing Strings would look like this:
List<Boxcar<String>> train = new ArrayList<Boxcar<String>>();
The ? is an example of a wildcard, while a T represents a type that is referenced inside the source of List. That point can be tricky to understand without a deeper understanding of Generics, but I wanted to be sure address it for completeness sake. Take a look at this page for more information about how to use Generics inside your code.
Looking at your revised question, I would direct you to this line of code:
public class Boxcar<T extends Comparable<T>> {
and then just below it this line:
private List<T> boxcar;
This means whatever type you pass to new Boxcar<type>() will be carried over to the inner list (and other methods that expect an object of type T).
Based on the wording of your original question it sounds like you want to create a list of boxcars.
Below is all you would need to do.
private List<Boxcar> boxcarList = new ArrayList<Boxcar>();
Related
I'm trying to read and write this ArrayList structured as well: ArrayList<ArrayList<Pair<Float,Float>>> points I've seen that the only way would by using the class inside the external ArrayList, but in this case I haven't it. This is my full class, how do I can implement it?
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pair;
import java.io.Serializable;
import java.util.ArrayList;
public class Cornice implements Serializable, Parcelable {
private String number;
private ArrayList<ArrayList<Pair<Float,Float>>> points;
public Cornice(String n, ArrayList<ArrayList<Pair<Float,Float>>> p) {
number = n;
if (p!=null) points = new ArrayList<>(p);
else points=new ArrayList<>();
}
protected Cornice(Parcel in) {
number = in.readString();
points = //MISSING
}
public String getNumber () {
return number;
}
public ArrayList<ArrayList<Pair<Float,Float>>> getPoints () {
return points;
}
public static final Creator<Cornice> CREATOR = new Creator<Cornice>() {
#Override
public Cornice createFromParcel(Parcel in) {
return new Cornice(in);
}
#Override
public Cornice[] newArray(int size) {
return new Cornice[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(number);
//MISSING
}
}
Pair is neither Parcelable, nor Serializable, so what you are trying to do won't work. You will have to change the data structure you use to hold the points to something else. For example you can convert it something like this:
private ArrayList<ArrayList<Float[]>> points;
or even (if you do not want to support null values) to:
private ArrayList<ArrayList<float[]>> points;
I am trying to model a train with a Java program.
Currently I have four classes:
Train,
BoxCar,
Cargo,
Person.
The BoxCar class has an array of Person and an array of Cargo. A BoxCar can only hold one type so when that type is given from the constructor,
I decide which array to use (either the people array or the cargo array). The thing is, I'd like to make that array inside BoxCar "generic" so that if there is another "kind" of type the user wants to use, it can be easily set.
They wouldn't need to declare another array inside the BoxCar class for that type and change the rest of the code.
How would I do this? I looked up Generic and Reflection but the examples I saw weren't exactly for my scenario and I'm learning this for the first time.
Can someone map out the right approach to take?
BoxCar:
class BoxCar {
String boxType;
int boxID;
int count;
boolean isEmpty;
Cargo cargo[];
Person people[];
int capacity;
BoxCar(String box_type, int ID, int cap) {
boxType = box_type;
boxID = ID;
isEmpty = true;
count = 0;
capacity = cap;
}
}
Person:
class Person {
String government_ID, name;
int age;
Person(String gov_ID, String Name, int Age) {
government_ID = gov_ID;
name = Name;
age = Age;
}
}
Cargo:
class Cargo {
String cargo_ID;
int height, weight;
Cargo(String c_id, int w, int h) {
cargo_ID = c_id;
height = h;
weight = w;
}
}
Maybe this helps you out
public class Train {
public static void main(String[] args) {
new Train();
}
public Train() {
List<Person> persons = new ArrayList<>();
persons.add(new Person("foo", "bar"));
BoxCar<Person> personBoxCar = new BoxCar<>(persons);
List<Cargo> cargo = new ArrayList<>();
cargo.add(new Cargo("test"));
BoxCar<Cargo> cargoBoxCar = new BoxCar<>(cargo);
}}
public class Person {
private String name;
private String surname;
public Person(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}}
public class Cargo {
private String cargoType;
public Cargo(String cargoType) {
this.cargoType = cargoType;
}
public String getCargoType() {
return cargoType;
}}
public class BoxCar<T> {
private List<T> myArray;
public BoxCar(List<T> myArray) {
this.myArray = myArray;
}}
The best way to accomplish that is using generics.
Generics are a facility of generic programming that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow “a type or method to operate on objects of various types while providing compile-time type safety”
https://en.wikipedia.org/wiki/Generics_in_Java
The generic E allows passing a type according to your needs.
class BoxCar<E> {
private int boxID;
private int count;
private boolean isEmpty;
private E target[];
private int capacity;
public BoxCar(int ID, int cap) {
boxID = ID;
isEmpty = true;
count = 0;
capacity = cap;
}
public setTarget(E target[]) {
thid.target = target;
}
}
Another approach is to use interfaces, for example this could be a solution:
Implementing an interface allows a class to become more formal about the behavior it promises to provide. Interfaces form a contract between the class and the outside world, and this contract is enforced at build time by the compiler. If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.
https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
import java.util.HashMap;
import java.util.Map;
public class A {
public static void main(String[] args) {
BoxCar<String, String> boxCar_1 = new BoxCar<>(new Person("gov_id", "name", 35), 1, 1);
BoxCar<String, String> boxCar_2 = new BoxCar<>(new Cargo("c_id", 1, 1), 1, 1);
}
}
/**
* This interface declares the
* methods for box targets.
*
* #param <T> for jey
* #param <E> for value
*/
interface BoxCarTarget<T, E> {
/**
* This method returns the data regarding to
* a specific BoxCar target.
*
* #return Map with specific data.
*/
Map<T, E> getPayload();
}
class BoxCar<T, E> {
private BoxCarTarget<T, E> target;
private int boxID;
private int count;
private boolean isEmpty;
private int capacity;
BoxCar(BoxCarTarget<T, E> target, int ID, int cap) {
this.target = target;
boxID = ID;
isEmpty = true;
count = 0;
capacity = cap;
/*
* Here you can handle the payload.
* I think we can use reflection for
* extracting data.
*/
Map<T, E> payload = this.target.getPayload();
}
}
/**
* Class person
*/
class Person implements BoxCarTarget<String, String> {
private String government_ID, name;
private int age;
Person(String gov_ID, String Name, int Age) {
government_ID = gov_ID;
name = Name;
age = Age;
}
/**
* This method returns the data regarding to
* a specific BoxCar target.
*
* #return Map with specific data.
*/
#Override
public Map<String, String> getPayload() {
Map<String, String> payload = new HashMap<>();
payload.put("government_ID", government_ID);
payload.put("name", name);
payload.put("age", String.valueOf(age));
return payload;
}
}
/**
* Class Cargo
*/
class Cargo implements BoxCarTarget<String, String> {
private String cargo_ID;
private int height, weight;
Cargo(String c_id, int w, int h) {
cargo_ID = c_id;
height = h;
weight = w;
}
/**
* This method returns the data regarding to
* a specific BoxCar target.
*
* #return Map with specific data.
*/
#Override
public Map<String, String> getPayload() {
Map<String, String> payload = new HashMap<>();
payload.put("cargo_ID", String.valueOf(cargo_ID));
payload.put("height", String.valueOf(height));
payload.put("weight", String.valueOf(weight));
return payload;
}
}
Hope this helps!
I misunderstood your question previously. Here is what it should be:
public class BoxCarContents {
...
}
public class Person extends BoxCarContents {
...
}
public class Cargo extends BoxCarContents {
...
}
public class BoxCar<E extends BoxCarContents> {
E[] contents;
public BoxCar(int capacity) {
contents = new E[n];
}
...
}
//Alternative way
public class BoxCar {
BoxCarContents[] contents;
public BoxCar(BoxCarContents[] boxContents) {
contents = boxContents;
}
...
}
Basically the <E extends BoxCarContents> means E can be anything that extends BoxCarContents.
I am trying to design a ride sharing system. Here is my base object
package rider;
import java.util.TreeMap;
public class Uber{
String driver;
TreeMap<Float,String> destination;
public Uber(String d)
{
driver=d;
destination = new TreeMap<Float,String>();
}
private void addTimeDest(float tm, String dest)
{
destination.put(tm, dest);
}
float getTsum() {
float tsum=0;
for (float f : this.destination.keySet())
tsum+=f;
return tsum;
}
}
So, each object has a driver and an associated time<->destination map for that driver. Ultimately, i want to sort a list of such objects by the time field i.e. the key of the treemap.
and here is the iterator class i created for the above
package rider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
public class UberIterator implements Iterator<Uber> {
int currIndex=0;
ArrayList<Uber> uList;
Comparator<Uber> timeComparator = new Comparator<Uber>(){
public int compare(Uber u1, Uber u2) {
return (int) (u1.getTsum()-u2.getTsum());
}
};
public UberIterator(ArrayList<Uber> nList)
{
uList=nList;
Collections.sort(uList,timeComparator);
}
public boolean hasNext() {
return currIndex<uList.size();
}
public Uber next() {
return uList.get(currIndex++);
}
#Override
public void remove() {
uList.remove(currIndex--);
}
public void remove(String d) {
int rindex=-1;
for(int u=0 ; u<currIndex; u++)
{
if(uList.get(u).driver.equals(d))
{
rindex=u;
break;
}
}
if(rindex<0)
System.out.println("Driver not found.");
else
{
uList.remove(rindex);
currIndex--;
}
}
public void remove(float tm) {
int rindex=Collections.binarySearch(uList, tm, timeComparator);
if(rindex<0)
{
System.out.println("Exact time not found. Closest will be removed.");
}
else
{
uList.remove(rindex);
currIndex--;
}
}
}
basically, with the comparator
Comparator<Uber> timeComparator = new Comparator<Uber>(){
public int compare(Uber u1, Uber u2) {
return (int) (u1.getTsum()-u2.getTsum());
}
};
i am trying to sort by the key of the internal treemap. but i get this error
The method binarySearch(List<? extends T>, T, Comparator<? super T>) in the type Collections is not applicable for the arguments (ArrayList<Uber>, float, Comparator<Uber>)
at
int rindex=Collections.binarySearch(uList, tm, timeComparator);
how should i correct my implementation?
Follow Up
is there a way to override Collections.binarySearch ? what if Uber implements Comparable and there i define the compare method as above? Shouldn't that automatically search with the time dimension? Otherwise what is the benefit of defining custom comparators for sorting? The sole reason i want to sort the list in a certain way is to be able to search it efficiently later on.
package rider;
import java.util.TreeMap;
public class Uber implements Comparable<Uber> {
String driver;
TreeMap<Float,String> destination;
public Uber(String d)
{
driver=d;
destination = new TreeMap<Float,String>();
}
private void addTimeDest(float tm, String dest)
{
destination.put(tm, dest);
}
public int compareTo(Uber u) {
return (int) (this.getTsum()-u.getTsum());
}
float getTsum() {
float tsum=0;
for (float f : this.destination.keySet())
tsum+=f;
return tsum;
}
}
int rindex=Collections.binarySearch(uList, tm, timeComparator);
You cannot search for a float in a List<Uber>.
Your alternatives...frankly aren't that great. You could create a fake Uber containing your tm value and pass that to Collections.binarySearch. You could use a library like Guava, call Lists.transform(ubers, getTmFunction) to create a view, and pass that to Collections.binarySearch. You could reimplement binary search yourself.
I am trying to develop a program that can sort an array of objects that are of different class types, but in the same hierarchy as one another. All of the objects are listed within the same array that I am trying to sort, and while I can alphabetically sort an array of objects that are of the same type easily enough, I cannot figure out how to sort everything all at once with the same Arrays.sort() method. Any help that anyone could provide would be greatly appreciated.
import java.util.Arrays;
public class Driver {
public static void main(String[] args) {
Vehicle[] machines = new Vehicle[3];//Example of an array that I can sort
machines[0] = new Vehicle("Giant Robot");
machines[1] = new Vehicle("Time Machine");
machines[2] = new Vehicle("Airplane");
Arrays.sort(machines);
for (int i = 0; i < machines.length; i++)
System.out.println(machines[i].getName());
Vehicle[] vehicles = new Vehicle[7];//example of an array that I cannot sort
vehicles[0] = new Car("Batmobile", 10);
vehicles[1] = new Helicopter("Batcopter", "x");
vehicles[2] = new Car("Jaguar", 6);
vehicles[3] = new Helicopter("RC Copter", "t");
vehicles[4] = new Car("Accelerator", 6);
vehicles[5] = new Helicopter("Stormshadow", "z");
vehicles[6] = new Car("Batmobile", 11);
}
}
**
public class Vehicle implements Comparable {
private String name;
public Vehicle(){
name = "no name";
}
public Vehicle(String newName){
name = newName;
}
public String getName(){
return name;
}
public int compareTo(Object o)
{
if ((o != null) &&
(o instanceof Vehicle))
{
Vehicle otherVehicle = (Vehicle) o;
return (name.compareTo(otherVehicle.name));
}
return -1;
}
}
**
public class Car extends Vehicle {
private int tireSize;
public Car(){
super();
tireSize = 0;
}
public Car(String newName, int newTireSize){
super(newName);
tireSize = newTireSize;
}
public int getSize(){
return tireSize;
}
}
**
public class Helicopter extends Vehicle {
private String bladeType;
public Helicopter(){
super();
bladeType = "none";
}
public Helicopter(String newName, String newBlade){
super(newName);
bladeType = newBlade;
}
public String getType(){
return bladeType;
}
}
Goal: You need to be able to compare a Vehicle to other of Vehicle.
To achieve that goal:
public class Vehicle implements Comparable<? extends Vehicle> {
....
public int compareTo(Object o) {
// Now, that the Comparable is for the type Vehicle
// you know that o is some kind of vehicle
// check vehicle related things
// number of seats, dogs, whatever
return -1;
}
}
You just need to adjust your code to:
class Vehicle implements Comparable<Vehicle> {
private String name;
/* ... */
#Override
public int compareTo(Vehicle vehicle) {
return name.compareTo(vehicle.getName());
}
}
In most cases, your classes should not implement Comparable, unless there is one and only one ordering that is always the correct one, like with numbers. Your vehicles can be sorted by name, by age, and probably by more criteria, so they should not implement Comparable.
Instead, you can pass the ordering function as a lambda function, at the time where you actually sort your vehicles:
Arrays.sort(machines, (left, right) -> left.getName().compareTo(right.getName()));
Or, equivalently:
Arrays.sort(machines, Comparator.comparing(Vehicle::getName));
This way you don’t need the implements Comparable anymore.
If you want to sort by vehicle type then you need to take class type into consideration, while sorting the element. Modify the compareTo() method as shown below:
public int compareTo(Object o){
if ((o != null) &&
(o instanceof Vehicle)){
Vehicle otherVehicle = (Vehicle) o;
return (otherVehicle.getClass().getSimpleName().equals(this.getClass().getSimpleName()) ?
name.compareTo(otherVehicle.name)
: otherVehicle.getClass().getSimpleName().compareTo(this.getClass().getSimpleName()));
}
return -1;
}
Ok, I have an object with multiple instance variables that I would like to sort by, so I read that i have to implement a comparator class and use it.
Basically its a plane class with PlaneSeats object as its member.
PlaneSeats has SeatID, CustomerID
I wish to print the occupied seats by CustomerIDs, does anyone know how?
//This Prints it by SeatID (Since it starts from 0)
for (int i = 0; i < seat.length; i++) {
if (seat[i].isOccupied()) {
System.out.println("SeatID " + seat[i].getSeatID() + " assigned to CustomerID " + seat[i].getCustomerID());
}
}
my failed Comparator code is as follows: I hope to NOT use a seperate class though, hopefully so sort of array.sort function?
import java.util.*;
public class Comparator implements Comparator<Plane> {
public int compare(Plane CustomerID[], Plane CustomerID[]) {
}
}
Arrays.sort(CustomerID, new Comparator<Plane>() {
public int compare(Plane p1, Plane p2) {
PlaneSeat ps1 = p1.getPlaneSeat();
PlaneSeat ps2 = p2.getPlaneSeat();
return ps1.getSeatID().compareTo(ps2.getSeatID());
}
});
This will sort on basis of SeatId. If you want to sort on basis of CustomerId, replace getSeatID() with getCustomerID().
This won't compile
public class Comparator implements Comparator<Plane> {
public int compare(Plane CustomerID[], Plane CustomerID[]) {
}
}
You are breaking the contract.
See this code for a possible solution.
PlaneSeat class definition
public class PlaneSeat {
//Create your custom comparator strategy
public static final Comparator<PlaneSeat> CUSTOMER_COMPARATOR = new CustomerComparator();
//fields
private final Integer customerID;
public PlaneSeat(Integer customerID){
this.customerID= customerID;
}
private static class CustomerComparator implements Comparator<PlaneSeat>{
#Override
public int compare(PlaneSeat o1, PlaneSeat o2) {
return o1.customerID.compareTo(o2.customerID);
}
}
#Override
public String toString() {
return "PlaneSeat [customerID=" + customerID + "]";
}
}
Plane class
public class Plane{
private List<PlaneSeat> seats;
public List<PlaneSeat> getSeats() {
return seats;
}
public void setSeats(List<PlaneSeat> seats) {
this.seats = seats;
}
public void sortSeatsByCustomer(){
Collections.sort(seats,PlaneSeat.CUSTOMER_COMPARATOR);
}
#Override
public String toString() {
return "Plane [seats=" + seats + "]";
}
}
Then in your client code:
public static void main(String args []){
List<PlaneSeat> seats = new ArrayList<>();
for(int i =10;i>0;i--)
seats.add(new PlaneSeat(i--));
Plane plane = new Plane();
plane.setSeats(seats);
System.out.println(plane);//print before sorting
plane.sortByCustomers();
System.out.println(plane);//after sorting by customer
}
You shouldn't name your class "Comparator", since that's already a Java interface name.
Plane CustomerID[]
This does not make sense.
Didn't I answer your prior question about seats?
Your PlaneSeat class should implement Comparable<PlaneSeat> and a method named
public int compareTo(PlaneSeat seat)
In this method, seat is the second seat, the object you're comparing with. The other object is
this
In this method, you can call the
getCustomerID()
method on the objects. It should look like:
public int compareTo(PlaneSeat seat) {
if (this.getCustomerID() > seat.getCustomerID()) return 1;
if (this.getCustomerID() < seat.getCustomerID()) return -1;
return 0;
}
If this gives you the reverse order of what you wanted, swap 1 and -1.
Before your comment
//This Prints it by SeatID (Since it starts from 0)
call
seat = Arrays.sort(seat);
to sort the seats.
You can't implement Comparator class again, it's defined as an interface and you have to implement it by naming a different class.