I need to iterate through and ArrayList of objects and look for a variable that has the same value for multiple objects. As the example below, I am looking through an ArrayList, that has a sub-class . All I want to do is find out if a house or condo share the same listing number for this example code. I tried using a double loop, and an enhanced loop with a method (sameListingNum) and am having trouble working it out.
Thank you
// main client class
public static void main(String[] args)
{
ArrayList<House> listings = new ArrayList();
listings.add(new House(0001, 200000.00));
listings.add(new House(0201, 200000.00));
listings.add(new House(0001, 200000.00));
listings.add(new House(0401, 200000.00));
listings.add(new House(0031, 200000.00));
listings.add(new Condo(0401, 200000.00, 4));
listings.add(new Condo(0001, 120000.00, 3));
listings.add(new Condo(0301, 220000.00, 2));
listings.add(new Condo(0001, 130000.00, 3));
listings.add(new Condo(0201, 130000.00, 3));
for(House currentHouse: listings)
System.out.println(currentHouse);
for(int i=0; i<listings.size()-1; i++)
{
for(int j=i+1; j<listings.size(); j++)
{
}
}
// House Class
public class House
{
public int listingNum;
public double price;
public House()
{
listingNum = 0;
price = 0.00;
}
public House(int newListingNum, double newPrice)
{
listingNum = newListingNum;
price = newPrice;
}
public int getListingNum()
{
return listingNum;
}
public double getPrice()
{
return listingNum;
}
public String toString()
{
return ("Listing number: "+listingNum+", Price: "+price);
}
public boolean sameListingNum(Object other)
{
if(!(other instanceof House))
return false;
else {
House objHouse = (House)other;
if(listingNum - objHouse.getListingNum() == 0)
{
System.out.println("Same listing numbers: "
+listingNum+", "+objHouse.getListingNum());
return true;
}
else
return false;
}
}
}
// Condo Class
public class Condo extends House
{
public int connectedUnits;
public Condo()
{
super();
connectedUnits = 0;
}
public Condo(int newListingNum, double newPrice, int newConUnits)
{
super(newListingNum, newPrice);
connectedUnits = newConUnits;
}
public double getPrice()
{
return price;
}
public int getListingNum()
{
return listingNum;
}
public int getConnectedUnits()
{
return connectedUnits;
}
public String toString()
{
return super.toString()+", Number of connected unints: "+connectedUnits;
}
public boolean sameListingNum(Object other)
{
if(!(other instanceof House))
return false;
else {
House objHouse = (House)other;
if(listingNum - objHouse.getListingNum() == 0)
{
System.out.println("Same listing numbers: "
+listingNum+", "+objHouse.getListingNum());
return true;
}
else
return false;
}
}
You can group it using a Map of List, like Map> groups.
Then you loop over you list and for each house/condo you put it in the group of the same listing number. At the end you will have a map where for each entry there are all houses/condos with same listing number.
Here a sample:
Map<Integer, List<House>> groups = new HashMap<Integer, List<House>>();
for (House house:listings) {
List<House> group = groups.get(house.getListingNum());
if (group == null) {
group = new ArrayList<House>();
groups.put(house.getListingNum(), group);
}
group.add(house);
}
for (Entry<Integer, List<House>> entry:groups.entrySet()) System.out.println("Listing Number "+entry.getKey()+" Houses/condos: "+entry.getValue());
Both of the other 2 answers will work alternativly you can implement comparable on the House... eg.
public class House implements Comparable<House>
#Override
public int compareTo(final House o) {
return listingNum - o.listingNum;
}
then inside your main method. Sort the Collection and check to see if the previous row has the same Id all the time.
Collections.sort(listings);
int previousListing = Integer.MIN_VALUE;
for (House currentHouse : listings) {
if (currentHouse.getListingNum() == previousListing){
System.out.println("Duplicate for " + currentHouse.getListingNum());
}
previousListing = currentHouse.getListingNum();
}
take your pick.
Try this:
foreach(House h in listings)
{
if(listings.Exists(p => p.sameListingNum(h)))
{
//do something
}
}
Related
Item.java
I have an item with variables name and weight
package com.company;
public class Item {
String name;
Double weight;
}
Bag.java
the bag can receive up to 20 kg items.
package com.company;
public class Bag {
Item [] myBags;
int itemCount;
Double currentWeight;
Bag(){
itemCount = 0;
currentWeight = 0.0;
myBags = new Item[50];
}
boolean canAddItem(Item item) {
if (currentWeight + item.weight > 20) {
return false;
} else {
return true;
}
}
void AddItem(Item item){
myBags[itemCount] = item;
currentWeight = currentWeight + myBags[itemCount].weight;
itemCount++;
}
}
Main.java
package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
Bag myBag = new Bag();
/*item 1*/
Item fishing_rod = new Item();
fishing_rod.name = "rod1";
fishing_rod.weight = 10.4;
if(myBag.canAddItem(fishing_rod)){
myBag.AddItem(fishing_rod);}
/*item 2*/
Item axe = new Item();
axe.name = "axe1";
axe.weight = 2.2;
if(myBag.canAddItem(axe)){
myBag.AddItem(axe);}
System.out.println(myBag.currentWeight);
//System.out.println(myBag.myBags); i want to show that's here
}
}
I added two objects to the bag . I want to show all the objects I have added in the bag.
How can I show ? How can I show this in java ?
Thanks for your help
You have to override the toString() method in your class:
For Item class first:
#Override
public String toString() {
return "Name: "+ name + ": weight "+ weight +"Kg";
}
then for Bag class
#Override
public String toString() {
return Arrays.toString(myBags);
}
In this way every time you print your bag you will get the content of it.
In Bag class:
public void printBag() {
for(int i =0; i< itemCount; i++) {
System.out.println("Name: " + myBags[i].name);
System.out.println("Weight: " + myBags[i].weight);
}
}
In main method:
myBag.printBag();
Define a function inside your Bag class:
public void printBag() {
for(Item element : myBags) {
System.out.println('Name: ' + element.name);
System.out.println('Weight: ' + element.weight);
}
}
And call it from the main:
myBag.printBag();
The goal of my program is to store data for students(First Name, Last Name, ID#).I'm trying to create 4 Arrays. One array will hold the combined value of each student object that I'm adding(myDB). The other 3 hold indexes to the original spot of each value(Fname,Lname,ID) and add them to an ordered array without sorting the array. The trouble I'm having is that once I add something to the Index Arrays and go to print them, it prints all of the IDs regardless of what object I call.
//class containing methods to list, add, and delete
//Class that declares the main database array that holds all three (ID,First,Last)
import java.io.FileInputStream;
import java.util.*;
public class DataBase
{
private String tempID, tempFname, tempLname;
private DataBaseArray myDB;
private int nextDBRecord;
private IndexArray ID;
private IndexArray First;
private IndexArray Last;
public DataBase()
{
nextDBRecord = 0;
myDB =new DataBaseArray(100);
ID=(new IndexArray(100));
First=new IndexArray(100);
Last=new IndexArray(100);
}
void addData(String last, String first, String id)
{
tempLname = new String(last);
tempFname = new String(first);
tempID = new String(id);
//ID.insert(new IndexRecord(tempID, nextDBRecord));
First.insert(new IndexRecord(tempFname,nextDBRecord));
Last.insert(new IndexRecord(tempLname,nextDBRecord));
//Adds to main DB with
myDB.getStudentArray()[nextDBRecord]= (new DataBaseRecord(tempLname,tempFname,tempID));
System.out.println(myDB.getStudentArray()[nextDBRecord]);
nextDBRecord++;
}
void addIt ()
{
Scanner keyb = new Scanner(System.in);
System.out.println("Please enter the ID for new student entry");
tempID=keyb.next();
ID.insert(new IndexRecord(tempID, nextDBRecord));
System.out.println("Please enter the first name of the new student");
tempFname=keyb.next();
First.insert(new IndexRecord(tempFname, nextDBRecord));
System.out.println("Please eneter the last name of the new student");
tempLname=keyb.next();
Last.insert(new IndexRecord(tempLname,nextDBRecord));
//Adds to main DB with
myDB.getStudentArray()[nextDBRecord]= (new DataBaseRecord(tempLname,tempFname,tempID));;
nextDBRecord++;
}
void findIt()
{
}
void list (int type, int order)
{
First.printIt(order);
}
}
//Class that creates the objects to add to Iarray Farray Iarray
//IndexArray is a static array
//Creates a single entry into the IndexArray
//Need a compareTo method that gives the where value of each object
public class IndexRecord
{
private String key; //Value
private int where; //Where it is at in DataBaseArray
IndexRecord (String value, int position)
{
setKey(new String(value));
where = position;
}
public String toString()
{
return getKey()+" "+ String.valueOf(where);
}
public String getKey() //Getter for key value of the new student that is being added
{
return key;
}
public void setKey(String key) //Setter for key value of the new student that is being added
{
this.key = key;
}
}
//Same as OrderedArray Class
//Add Iterator methods. Instead of printing here, tell DataBase class what DatabaseRecord objects to print
public class IndexArray
{
private static IndexRecord[] irArray;
private int nOfElem; //Should be the same for each array so only 1 counter is needed
private int maxSize;
private int theIterator;
public IndexArray(int size)
{
nOfElem = 0;
maxSize=size;
irArray = new IndexRecord[size];
}
//-----------------------------Getters and Setters-------------------------------------
public int size() //Getter to find num of elements in array that can be called in other class
{ return nOfElem; }
public IndexRecord[] getIRarray()
{
return irArray;
}
//---------------------Iterator Methods-----------------------------------------------------
void iteratorToFront()
{
theIterator=(nOfElem>0? 0 : -1);
}
void iteratorToBack()
{
theIterator=(nOfElem>0 ? nOfElem-1 : -1);
}
boolean hasNext()
{
return (theIterator==nOfElem-1? false:true );
}
boolean hasPrevious()
{
return (theIterator==0? false : true);
}
public IndexRecord getIterator()
{
return(theIterator==-1 ? null :irArray[theIterator]);
}
int getNext()
{
theIterator=(hasNext()? theIterator+1: -1);
return(theIterator==-1? null : theIterator);
}
int getPrevious()
{
theIterator=(hasPrevious()? theIterator-1:-1);
return (theIterator==-1? null : theIterator);
}
//------------------Methods Called In Main---------------------------------------
public boolean insert(IndexRecord ir)
{
if(maxSize==nOfElem) return false;
int j;
for(j=nOfElem-1;j>=0;j--)
{
if(irArray[j].getKey().compareToIgnoreCase(ir.getKey())<0)break;
{
irArray[j+1]=irArray[j]; //Pushes all objects down to make room for new one
}
}
irArray[j+1]=ir;
nOfElem++;
return true;
}
public int find(String searchKey)
{
int lowerBound = 0;
int upperBound = nOfElem-1;
int currentRef;
while(true)
{
currentRef = (lowerBound + upperBound) / 2;
String tempValue = String.valueOf(irArray[currentRef].getKey());
if(tempValue.compareTo(searchKey) == 0)
return currentRef;
else if (lowerBound > upperBound)
return nOfElem; //returns a pointer to an empty slot
else
{
if(tempValue.compareTo(searchKey) > 0)
lowerBound = currentRef++;
else
upperBound = currentRef - 1;
}
}
}
//delete
public void printIt(int order)
{
switch(order)
{
case -1:
iteratorToBack();
break;
case 1:
iteratorToFront();
while(hasNext())
{
System.out.println(irArray[getNext()]);
}
break;
default:
}
}
}
I have a set of objects. This objects calculate some numbers based on request parameters. Let's call them calculators. Each calculator has description where specified type of requests that this calculator the most suitable for.
For example,
Calculator1 : with this parameters : price > 10, gender = male, geo_id = 1, 2 or 3.
Calculator2 : with this parameters : price < 5, gender = male, geo_id = 1, 2.
For request : price = 11, gender = male, geo_id = 2 I should get calculator1 like the most suitable and then calculator2.
For request : price = 4, gender = male, geo_id = 2 I should get calculator2 and then calculator1.
For request : price = 3, gender = female, geo_id = 5 I should get only the second one.
Now I'm doing it with Lucene, but it's not really fit for this task. Can you recommend me some library or approach?
My suggestion would be to use a comparator. See a sketch of the classes below.
import java.util.HashMap;
import java.util.Map;
public abstract class Calculator {
public static Map<String, Integer> weights;
static {
weights = new HashMap<String, Integer>();
weights.put("price", 10);
weights.put("gender", 2);
weights.put("geo", 5);
}
public abstract int calculate(Map<String, Integer> request);
public abstract int fitnessFor(Map<String, Integer> request);
}
You can use the weights to adjust relative importance of the individual request parameters.
import java.util.Map;
public class Calculator1 extends Calculator {
public int calculate(Map<String, Integer> request) {
return -1;
}
#Override
public int fitnessFor(Map<String, Integer> request) {
int fitness = -1;
Integer price = request.get("price");
if (price == null)
return fitness;
if (price > 10)
fitness += weights.get("price");
return fitness;
}
public String toString() { return "Calculator1"; }
}
Calculator1 cares only about the pricey items.
import java.util.Map;
public class Calculator2 extends Calculator {
public int calculate(Map<String, Integer> request) {
return -1;
}
#Override
public int fitnessFor(Map<String, Integer> request) {
int fitness = -1;
Integer price = request.get("price");
if (price == null)
return fitness;
if (price < 5)
fitness += weights.get("price");
Integer gender = request.get("gender");
if (gender == null)
return fitness;
if (gender == 1)
fitness += weights.get("gender");
return fitness;
}
public String toString() { return "Calculator2"; }
}
Calculator2 cares about the less pricey items esp. if they are for gender 1.
The comparator just compares Calculators by their fitness relative to the request:
import java.util.Comparator;
import java.util.Map;
public class CalcComparator implements Comparator<Calculator> {
private Map<String, Integer> request;
public CalcComparator(Map<String, Integer> request) {
this.request = request;
}
#Override
public int compare(Calculator c1, Calculator c2) {
int c1Fitness = c1.fitnessFor(request);
int c2Fitness = c2.fitnessFor(request);
if (c1Fitness == c2Fitness)
return 0;
if (c1Fitness < c2Fitness)
return 1;
return -1;
}
}
Try it out with:
public class Main {
public static void main(String[] args) {
Map<String, Integer> request = new HashMap<String, Integer>();
request.put("price", 5);
request.put("gender", 1);
List<Calculator> calculators = new ArrayList<Calculator>();
calculators.add(new Calculator1());
calculators.add(new Calculator2());
Collections.sort(calculators, new CalcComparator(request));
System.out.println("For request: "+request);
for (Calculator c : calculators) {
System.out.println("\t"+c.toString() + "( fitness " + c.fitnessFor(request) + ")");
}
}
}
This is just a sketch to illustrate the idea. You will probably want to introduce an enum for the request parameters, maybe introduce a Request class, most likely change completely how fitness is computed, make some of the fields private and encapsulate them, etc.
The advantage is that you easily get an ordering of all the Calculators based on their fitness for the request.
Provided that I understood you correctly, I would suggest that you use the Specification design pattern which is used in cases like this. There's no need in such a fancy library like Lucene for such a simple task. The advantage of the Specification pattern is that it keeps all the filtering logic grouped and encapsulated. Your implementation may vary, but below is a simple example of what it could look like
public interface Specification<T> {
boolean isSatisfiedBy(T candidate);
Specification<T> and(Specification<T> specification);
Specification<T> or(Specification<T> specification);
Specification<T> not(Specification<T> specification);
}
public abstract class Calculator {
// ...
}
public class Calculator1 extends Calculator implements Specification<Request> {
public boolean isSatisfiedBy(Request request) {
// check if the request fits this calculator
}
}
public class Calculator2 extends Calculator implements Specification<Request> {
public boolean isSatisfiedBy(Request request) {
// check if the request fits this calculator
}
}
You can then have a collection or a pool of calculators such that
public class Calculators {
private final List<RequestSpecification> calculators;
public Calculator getOneSuitedFor(Request request) {
for (Calculator calculator : calculators) {
if (calculator.isSatisfiedBy(request)) {
return calculator;
}
}
return null;
}
}
And here how you would use it
Calculator calculator = Calculators.getOneSuitedFor(request);
Or, if needed, you can always go on and expand on it by making use of composition (see the reference link above) which allows for logic chaining and combining of different specifications depending on the context. This, however, would require a little bit different class design from that of above, but is more flexible
final Request request;
Specification<Calculator> price = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.supportsPrice(request.getPrice());
}
};
Specification<Calculator> gender = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.supportsGender(request.getGender());
}
};
Specification<Calculator> region = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.supportsRegion(request.getRegion());
}
};
Specification calcSpec = price.and(gender).and(region);
boolean isSatisfied = calcSpec.isSatisfiedBy(calculator);
Another interesting example is to use named specifications
Specification<Calculator> teenager = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.getAge() >= 13 && calculator.getAge() <= 19;
}
};
Specification<Calculator> male = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.getGender().equals("male");
}
};
Specification<Calculator> fromEurope = new Specification<>() {
public boolean isSatisfiedBy(Calculator calculator) {
return calculator.getRegion().equals("Europe");
}
};
Specification<Calculator> calcSpec = teenager.and(male).and(fromEurope);
boolean isSatisfied = calcSpec.isSatisfiedBy(calculator);
You could maybe try something like this:
public enum Calculator
{
CALC1
{
#Override
protected int matchCount( Map parameters )
{
// TODO count how many conditions match
return 0;
}
#Override
protected int calc( Map parameters )
{
// TODO
return 0;
}
},
CALC2
{
#Override
protected int matchCount( Map parameters )
{
// TODO count how many conditions match
return 0;
}
#Override
protected int calc( Map parameters )
{
// TODO
return 0;
}
};
protected abstract int matchCount( Map parameters );
protected abstract int calc( Map parameters );
public int doCalc( Map parameters )
{
Calculator mostSuited = null;
int maxCount = 0;
for ( Calculator calc : values() )
{
int matchCount = calc.matchCount( parameters );
if ( matchCount > maxCount )
{
mostSuited = calc;
}
}
return mostSuited.calc( parameters );
}
}
The way you would use the above is by invoking: int result = Calculator.doCalc( parameters )
Create a Calculator base class :
public static abstract class Calculator {
// This Contains the common score calculation methods.
public int getScore(int price, String gender, int geo_id) {
int score = 0;
if (gender.equalsIgnoreCase("male"))
score++;
if (getGeoIds().contains(geo_id))
score++;
return score;
}
public ArrayList<Integer> getGeoIds() {
// Fetching the common list of geo points to be compared.
ArrayList<Integer> lst = new ArrayList<Integer>();
lst.add(1);
lst.add(2);
return lst;
}
public abstract void doCalculation();
}
Then create your calculator classes by extending from this base.
public static class Calcualtor1 extends Calculator {
#Override
public int getScore(int price, String gender, int geo_id) {
// fetching score from common score calculation.
int score = super.getScore(price, gender, geo_id);
// Adding its own score logic.
if (price > 10)
score++;
return score;
}
#Override
public void doCalculation() {
// Do your actual work.
}
#Override
public ArrayList<Integer> getGeoIds() {
ArrayList<Integer> lst = super.getGeoIds();
// Adding the geo id to compare for this calculator.
lst.add(3);
return lst;
}
}
public static class Calcualtor2 extends Calculator {
#Override
public int getScore(int price, String gender, int geo_id) {
// fetching score from common score calculation.
int score = super.getScore(price, gender, geo_id);
// Adding its own score logic.
if (price < 5)
score++;
return score;
}
#Override
public void doCalculation() {
// Do your actual work.
}
}
Initialise values :
//To store the list of available calculators.
private static ArrayList<Class<? extends Calculator>> calculators;
static {
//Initializing the calculator list in static constructor.
calculators = new ArrayList<Class<? extends Calculator>>();
calculators.add(Calcualtor1.class);
calculators.add(Calcualtor2.class);
}
Actual processing :
public static void main(String[] args) {
int price = 10;
String gender = "male";
int geo_id = 2;
Calculator calculator = null;
int score = 0;
for (Class<? extends Calculator> calClass : calculators) {
Calculator cal = null;
try {
cal = calClass.newInstance();
} catch (Exception e) {
continue;
}
int calScore = cal.getScore(price, gender, geo_id);
if (calScore > score) {
calculator = cal;
score = calScore;
}
}
if (calculator != null) {
calculator.doCalculation();
}
}
Im trying to sort my planes by Ascending and Descending order. I have a hashmap of planes and i want to compare them so that i can get the next plane due and last plane due by sorting the map by timeLimitBeforeLand. I wrote a compareTo method which looks like :
//---------------------------------------------------------------------------------------
// CompareTo() used with the Comparable implementation.
//---------------------------------------------------------------------------------------
public int compareTo(Object arg0)
{
if((arg0 != null) && (arg0 instanceof Plane))
{
Plane p = (Plane) arg0;
return (int)Math.ceil(this.timeLimitBeforeLand - p.getLimitBeforeLand());
}
return 0;
}
CompareTo takes timeLimitBeforeLand:
// ---------------------------------------------------------------------------------------
// Name: getTimeLimitBeforeLand.
// Description: Get the time before every plane is going to land.
//---------------------------------------------------------------------------------------
public double getTimeLimitBeforeLand()
{
double fuelConsumption;
double timeLimitBeforeLand = 0;
for (TreeMap<String, Plane> theEntry : airlineMap.values()) {
for (Plane aPlane : theEntry.values()) {
if (aPlane.getPlaneType() == aPlane.getPlaneType().AIRBUS) {
System.out.println(" ");
System.out.println(aPlane);
fuelConsumption = 2;
timeLimitBeforeLand = (double) (aPlane.getFuelRemaining() / fuelConsumption);
System.out.println(timeLimitBeforeLand + " minutes to land.");
System.out.println(" ");
} else if (aPlane.getPlaneType() == aPlane.getPlaneType().CORPORATE) {
System.out.println(" ");
System.out.println(aPlane);
fuelConsumption = 3;
timeLimitBeforeLand = (aPlane.getFuelRemaining() / fuelConsumption);
System.out.println(timeLimitBeforeLand + " minutes to land.");
System.out.println(" ");
} else if (aPlane.getPlaneType() == aPlane.getPlaneType().PRIVATE) {
System.out.println(" ");
System.out.println(aPlane);
fuelConsumption = 4;
timeLimitBeforeLand = (double) (aPlane.getFuelRemaining() / fuelConsumption);
System.out.println(timeLimitBeforeLand + " minutes to land.");
System.out.println(" ");
}
}
}
return timeLimitBeforeLand;
}
My attempt so far in the mainApp:
TreeMap<String, PlaneStore> map = new TreeMap<String, PlaneStore>();
ArrayList<Plane> copyList = new ArrayList<Plane>(map.);
Plane comp = new Plane();
Collections.sort(copyList, plane);
Plane Class:
//---------------------------------------------------------------------------------------
// Name: Imports.
// Description: To allow the use of different Java classes.
//---------------------------------------------------------------------------------------
import java.io.Serializable;
//---------------------------------------------------------------------------------------
//Name: Class declaration.
//---------------------------------------------------------------------------------------
public class Plane implements Comparable, Serializable
{
//---------------------------------------------------------------------------------------
// Variable declarations.
//---------------------------------------------------------------------------------------
private String flightNumber;
public String airlineName;
private double fuelRemaining;
private int overdue;
private int passengerNumber;
//---------------------------------------------------------------------------------------
// Enum declaration.
//---------------------------------------------------------------------------------------
private AIRPLANETYPE planeType;
private boolean isLanded = false;
public double timeLimitBeforeLand;
//---------------------------------------------------------------------------------------
// Enum Constuctor.
//---------------------------------------------------------------------------------------
public enum AIRPLANETYPE
{
AIRBUS("1"), CORPORATE("2"), PRIVATE("3");
private String planeName;
private AIRPLANETYPE(String planeName)
{
this.planeName = planeName;
}
public String getPlaneName()
{
return this.planeName;
}
}
//---------------------------------------------------------------------------------------
// Constructor.
//---------------------------------------------------------------------------------------
public Plane(String flightNumber, String airlineName,
double fuelRemaining, int overdue, int passengerNumber,
AIRPLANETYPE planeType, boolean isLanded)
{
this.flightNumber = flightNumber;
this.airlineName = airlineName;
this.fuelRemaining = fuelRemaining;
this.passengerNumber = passengerNumber;
this.overdue = overdue;
this.planeType = planeType;
this.isLanded = isLanded;
}
//---------------------------------------------------------------------------------------
// Getters and Setters.
//---------------------------------------------------------------------------------------
public String getAirlineName()
{
return airlineName;
}
public void setAirlineName(String airlineName)
{
this.airlineName = airlineName;
}
public void setOverdue(int overdue)
{
this.overdue = overdue;
}
public int getOverdue()
{
return overdue;
}
public String getFlightNumber()
{
return flightNumber;
}
public void setFlightNumber(String flightNumber)
{
this.flightNumber = flightNumber;
}
public double getFuelRemaining()
{
return fuelRemaining;
}
public void setFuelRemaining(double fuelRemaining)
{
this.fuelRemaining = fuelRemaining;
}
public int getPassengerNumber()
{
return passengerNumber;
}
public void setPassengerNumber(int passengerNumber)
{
this.passengerNumber = passengerNumber;
}
public AIRPLANETYPE getPlaneType()
{
return planeType;
}
public void setPlaneType(AIRPLANETYPE planeType)
{
this.planeType = planeType;
}
public boolean isLanded()
{
return isLanded;
}
public void setLanded(boolean isLanded)
{
this.isLanded = isLanded;
}
public double getLimitBeforeLand()
{
return timeLimitBeforeLand;
}
public void setTimeLimitBeforeLand(double timeLimitBeforeLand)
{
this.timeLimitBeforeLand = timeLimitBeforeLand;
}
//---------------------------------------------------------------------------------------
// CompareTo() used with the Comparable implementation.
//---------------------------------------------------------------------------------------
public int compareTo(Object arg0)
{
if((arg0 != null) && (arg0 instanceof Plane))
{
Plane p = (Plane) arg0;
return (int)Math.ceil(this.timeLimitBeforeLand - p.getLimitBeforeLand());
}
return 0;
}
//---------------------------------------------------------------------------------------
// toString().
//---------------------------------------------------------------------------------------
public String toString()
{
return "Plane: flightNumber=" + flightNumber + "."
+ " airlineName=" + airlineName + "."
+ " fuelRemaining=" + fuelRemaining + " litres."
+ " overdue=" + overdue + " minutes."
+ " passengerNumber="+ passengerNumber + "."
+ " airplaneType=" + planeType +
"hasLanded=" + isLanded+ ".\n";
}
}
The second argument in Collections.sort is for a Comparator not a Plane. Since I saw no mention of a Comparator, you should be able to use the natural order (defined by the compareTo method in your Plane object) and not have a second argument in the Collections.sort
EDIT: Unless you have just excluded that code, you aren't creating any Plane instances and you're using empty collections here...
TreeMap<String, PlaneStore> map = new TreeMap<String, PlaneStore>();
ArrayList<Plane> copyList = new ArrayList<Plane>(map.);
and you will be sorting by PlaneStores so you have to obtain all the Planes in each PlaneStore and add them to your copyList before sorting.
I would consider researching each of the Collections a little more and deciding what the best one for your need would be.
I have used HashMap in Java a lot but has never encountered this behavior. I have to types, Item and ItemGroup. They are defined as shown in the following codes snippets.
public class Item {
String id;
float total;
}
public class ItemGroup {
String keyword;
int frequency;
List<Item> items;
}
So ItemGroup consists of 0..* items. These items have a keyword in common and the keyword appears in the system with some frequency. Now the fun part, I have following method that given a list of items creates a list of groups.
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process keywords
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(items[i]);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(items[i]);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
The part where it gets strange is when adding the item to an itemgroup (the line group.getItems().add(items[i]);). During rehashing the group loses its items in a strange way. Using Debugging I can see that the group contains the item just after the operation but latter on, e.g. when returning the value of the method, all the groups has lost their items.
I tried this:
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(item);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(item);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
but got the same result. The following solution, however, works just fine.
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(item);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(item);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
The method EconomFactory.eINSTANCE.createItemGroup() is implemented as follow:
public ItemGroup createItemGroup() {
ItemGroupImpl itemGroup = new ItemGroupImpl();
return itemGroup;
}
where ItemGroupImpl is the implementation of ItemGroup, e.i. it subclasses the ItemGroup. It is because I use EMF (Eclipse Modeling Framework).
Can anyone please explain this behavior (why the ItemGroup objects lose their items)?
Here is the codes for ItemGroup and ItemGroupImpl. The same way looks the codes for Item and ItemImpl.
public interface ItemGroup extends EObject {
String getKeyword();
void setKeyword(String value);
int getFrequency();
void setFrequency(int value);
EList<Item> getItems();
void incrementFrequency();
}
public class ItemGroupImpl extends EObjectImpl implements ItemGroup {
protected static final String KEYWORD_EDEFAULT = null;
protected String keyword = KEYWORD_EDEFAULT;
protected static final int FREQUENCY_EDEFAULT = 0;
protected int frequency = FREQUENCY_EDEFAULT;
protected EList<Item> items;
protected ItemGroupImpl() {
super();
}
#Override
protected EClass eStaticClass() {
return EconomPackage.Literals.ITEM_GROUP;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String newKeyword) {
String oldKeyword = keyword;
keyword = newKeyword;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET,
EconomPackage.ITEM_GROUP__KEYWORD, oldKeyword, keyword));
}
public int getFrequency() {
return frequency;
}
public void setFrequency(int newFrequency) {
int oldFrequency = frequency;
frequency = newFrequency;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET,
EconomPackage.ITEM_GROUP__FREQUENCY, oldFrequency, frequency));
}
public EList<Item> getItems() {
if (items == null) {
items = new EObjectContainmentEList<Item>(Item.class, this,
EconomPackage.ITEM_GROUP__ITEMS);
}
return items;
}
public void incrementFrequency() {
this.frequency = getFrequency() + 1;
}
#Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID,
NotificationChain msgs) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__ITEMS:
return ((InternalEList<?>)getItems()).basicRemove(otherEnd,
msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
#Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
return getKeyword();
case EconomPackage.ITEM_GROUP__FREQUENCY:
return getFrequency();
case EconomPackage.ITEM_GROUP__ITEMS:
return getItems();
}
return super.eGet(featureID, resolve, coreType);
}
#SuppressWarnings("unchecked")
#Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
setKeyword((String)newValue);
return;
case EconomPackage.ITEM_GROUP__FREQUENCY:
setFrequency((Integer)newValue);
return;
case EconomPackage.ITEM_GROUP__ITEMS:
getItems().clear();
getItems().addAll((Collection<? extends Item>)newValue);
return;
}
super.eSet(featureID, newValue);
}
#Override
public void eUnset(int featureID) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
setKeyword(KEYWORD_EDEFAULT);
return;
case EconomPackage.ITEM_GROUP__FREQUENCY:
setFrequency(FREQUENCY_EDEFAULT);
return;
case EconomPackage.ITEM_GROUP__ITEMS:
getItems().clear();
return;
}
super.eUnset(featureID);
}
#Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
return KEYWORD_EDEFAULT == null ? keyword != null :
!KEYWORD_EDEFAULT.equals(keyword);
case EconomPackage.ITEM_GROUP__FREQUENCY:
return frequency != FREQUENCY_EDEFAULT;
case EconomPackage.ITEM_GROUP__ITEMS:
return items != null && !items.isEmpty();
}
return super.eIsSet(featureID);
}
#Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer();
result.append("(keyword: ");
result.append(keyword);
result.append(", frequency: ");
result.append(frequency);
result.append(')');
return result.toString();
}
}
In your second set of Code, where is I intialized?
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
The variable i has not been initialized in this context, so it could be any value (since its not blowing up, I assume you have a global "i" somehwere else in your code, and you are starting your method with that value instaed of 0.
In your code that is working you have i initialized in the method before you access it :
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
So, that is my guess as to why you are seeing the behavior you are seeing... ALWAYS INITIALIZE VARIABLES BEFORE ACCESSING THEM.
Tell us please what happens in EconomFactory.eINSTANCE.createItemGroup() ? I cannot tell if a unique instance with a unique items List is created each time.
I tried it out with some modifications (I am not currently using Java 6 so can't use String.isEmpty) and assuming regular object creation and it works for me. See below my runnable example (something like which you should post next time you ask a question):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ItemGrouper {
public static class Item {
String id;
float total;
Item(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
public static class ItemGroup {
String keyword;
int frequency;
List<Item> items = new ArrayList<ItemGrouper.Item>();
public void incrementFrequency() {
frequency++;
}
public List<Item> getItems() {
return items;
}
public void setKeyword(String string) {
keyword = string;
}
#Override
public String toString() {
return String.format("key=%s freq=%s", keyword, frequency);
}
}
public static ItemGroup[] createGroups(Item[] items) {
Map<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i = 0; i < items.length; i++) {
words = items[i].getId().split(" ");
// Process keywords
for (int j = 0; j < words.length; j++) {
if (words[j].length() == 0) {
break;
}
ItemGroup group = groups.get(words[j]);
if (group == null) {
group = new ItemGroup();
group.setKeyword(words[j]);
groups.put(words[j], group);
}
group.incrementFrequency();
group.getItems().add(items[i]);
}
}
return groups.values().toArray(new ItemGroup[0]);
}
public static void main(String[] args) {
Item[] items = new Item[] {new Item("one two"), new Item("two three")};
ItemGroup[] itemgroups = createGroups(items);
System.out.println(Arrays.toString(itemgroups));
}
}
Output:
[key=one freq=1, key=two freq=2, key=three freq=1]