Converts array to LinkedList - java

I would like to convert the following code from array to any other way (the most important is effective) which means that there is infinite space and I will not have to set the length of the array.
How can this be done? How can I set up an unlimited cities? using LinkedList
The idea is that it is possible to define a certain country in which certain cities are stored (the name of the city, the city center, the central bus station,... - as in the picture below) - In my code MAX_NUM_CITIES = 1000;
My Code:
public class Country {
//instance variables
private String _countryName; // name of the country
private City[] _cities; // Array of the cities
private int _noOfCities; //number of cities in a country
public void CityArray() {
_cities = new City[MAX_NUM_CITIES];
_noOfCities = 0;
}
//constants:
public final int MAX_NUM_CITIES = 1000;
/**
* Constructer for object in Country class construct Country with info accordingly
* #param countryName represents the name of country
* #param cities represents the cities array
* #param noOfCities represents the number of cities
*/
public Country(String countryName) {
this._countryName = _countryName;
this._noOfCities = _noOfCities;
City[] cities = new City[MAX_NUM_CITIES];
}
boolean addCity(java.lang.String cityName, double XcityCenter, double YcityCenter, double XStationPoint, double YStationPoint, long numOfResidents, int numOfNeighborhoods) {
if (_noOfCities <= MAX_NUM_CITIES) return false;
_cities[_noOfCities++] = new City(cityName, XcityCenter, YcityCenter, XStationPoint, YStationPoint, numOfResidents, numOfNeighborhoods);
return true;
}
public long getNumOfResidents() {
long SumOfCities = 0;
if (_noOfCities > 0) //empty Array
{
SumOfCities = _cities[0].getNumOfResidents();
for (int i = 1; i < _noOfCities; i++)
SumOfCities += _cities[i].getNumOfResidents();
} else
SumOfCities = 0;
return SumOfCities;
}
public String getCountryName() {
return this._countryName;
}
public int getNumOfCities() {
return this._noOfCities;
}
public City[] getCities() {
int noOfCities = this._noOfCities;
City[] cities = new City[noOfCities];
for (int i = 0; i < _noOfCities; i++) cities[i] = new City(this._cities[i]);
return cities;
}
public String toString() {
if (_noOfCities == 0) //empty Array
System.out.println("There are no cities in this country ");
else
for (int i = 0; i < _noOfCities; i++) _cities[i].toString();
return toString();
}
}

I would step away from arrays if the length is:
unknown
can change
I suggest using one of the different List implementations from the JDK, specifically ArrayList and LinkedList.
The first uses an internal array which may be expanded if an element is added and would lead to the array being too small (it does this all by itself, so no need to worry).
The second is a node list, which means that for every element you add, a new (internal) node object is appended to the last node.
You'd of course have to change your code for this.
Define your _cities to be a List<City>: private List<City> _cities
Initialize that with the wanted implementation in the constructor: _cities = new ArrayList<>(); or _cities = new LinkedList<>();
In your add method you can just call: _cities.add(new City(cityName, XcityCenter, YcityCenter, XStationPoint, YStationPoint, numOfResidents, numOfNeighborhoods));
In your getNumOfResidents you can use the following snippet (which uses Java streaming api introduced in java 8):
return _cities.stream()
.mapToLong(City::getNumOfResidents)
.sum();
for getCities() you'd have to change the return type to List<City> and use the following: return new ArrayList<>(_cities) or return new LinkedList<>(_cities) depending on the implementation you want to use.

Related

sort array of objects java with different properties

I have an object array containing two fields per object.
I have to write a method that will sort my array by the first field.
I already have a method which extracts the first field from each object
I always get an error message when I call my method to sort.
Here is my code:
public static void trier(String[]code, String[]nom, int nbObj) {
for(int i = 0; i < nbObj-1; i++) {
int indMin = i;
for (int j = i+1; j < nbObj; j++)
if (code[j].compareTo(code[indMin]) < 0)
indMin = j;
if (indMin != i) {
// permutation :
String tempo = code[i];
code[i] = code[indMin];
code[indMin] = tempo;
// permutation :
String temp = nom[i];
nom[i] = nom[indMin];
nom[indMin] = temp;
}
}
}
and the call :
Classe.trier(tableau, tableau, nbObj);
I also tried Class.sort(array.getCode(), array.getName(), nbStudent);
But I still have compilation errors
thank you in advance for your help
First of all, you don't have to use 2 separate arrays to contain your data. You can put everything in a single array, but better way is to use Java Collections. Perfect choice is ArrayList. However, you still better combine two fields into a single object. You can do it like this:
public class MyObject {
String code;
String nom;
MyObject(String code, String nom) {
this.code = code;
this.nom = nom;
}
}
Now you have a class containing 2 fields. Your aim is to sort a collection of such objects by their second field (nom). You can do this easily since Java 8:
public static void sort1(ArrayList<MyObject> list) {
list.sort((obj1, obj2) -> obj1.nom.compareTo(obj2.nom));
}
Or
public static void sort2(ArrayList<MyObject> list) {
list.sort(Comparator.comparing(MyObject::getNom));
} // However for this you need to add method getNom to MyObject
Remember to put your objects in the collection properly.
For example:
MyObject a = new MyObject("abc", "abide");
MyObject b = new MyObject("cab", "whatever you want");
ArrayList<MyObject> list = new ArrayList<>();
list.add(a);
list.add(b);
trier(list);

How to search specific word position in array of Strings

A few questions. I'm creating a method that searches through an array of element objects (where each element object has been initialized with [atomicNumber abbreviation name atomicWeight]). I also need to return 'a reference to the element'-- not exactly sure how to do this. The user inputs an abbreviation in main, then the findAbbreviation method is used on an array. The toString method formats and returns each datatype as a String. How might I search for the abbreviation position in any given object for the entire array. And how do I return a reference to that 'element' object.
public class PeriodicTable {
private final int MAX_ELEMENTS = 200;
private PeriodicElement[] table;
private int actualSize;
public PeriodicTable() throws IOException{
table = new PeriodicElement[MAX_ELEMENTS];
Scanner input = new Scanner(new File("file name here"));
int index = 0;
while(input.hasNext() && index < MAX_ELEMENTS) {
int aN = input.nextInt();
String abbr = input.next();
String name = input.next();
double aW = input.nextDouble();
table[index] = new PeriodicElement(aN, abbr, name, aW);
index++;
}
input.close();
actualSize = index;
}
public String findAbbreviation(String abbreviationP){
boolean found = false;
int index = 0;
while(found && index < MAX_ELEMENTS){
if (table[index] = table[abbreviationP]){
found = true;
return table[index].toString;
}
index++;
}
return null;
}
}
class PeriodicElement {
private int atomicNumber;
private String abbreviation, name;
private double atomicWeight;
public PeriodicElement(int atomicNumberP,
String abbreviationP, String nameP,
double atomicWeightP){
atomicNumber = atomicNumberP;
abbreviation = abbreviationP;
name = nameP;
atomicWeight = atomicWeightP;
}
First, you would need an array or collection of Elements. This could be an instance variable of the class you are currently writing which includes 'findAbbreviation'.
Second, an "Element" could simply have an attribute variable like "abbreviation" as an instance variable of the Element class, and you may just be able to call the findAbbreviation on the list and search for that abbreviation specifically in the abbreviation instance variable. It is unlikely that you could search on the actual name to find the abbreviation, because, for example: Gold's "abbreviation" is AU.
Could you show how your list of elements is defined as well as the class that defines the Elements?
If you are simply looking through a list of abbreviations of elements (as your current code suggests), you may just have to fix your current code to do an equals comparison correctly:
public String findAbbreviation(String abbreviationP){
boolean found = false;
int index = 0;
while(!found && index < MAX_ELEMENTS){ //this should be !found instead of found
if (table[index].equals(abbreviationP)) { // you previously had an assignment statement in this if
found = true;
return table[index].toString;
}
index++;
}
return null;
}
Updating answer to reflect update to the question:
First, you will need to provide a method in the PeriodicElement class to get the instance variable "abbreviation".
This is a standard "getter":
public String getAbbreviation() {
return abbreviation;
}
Second, you'll want to update your findAbbreviation method to utilize this new getter:
public PeriodicElement findAbbreviation(String abbreviationP){
boolean found = false;
int index = 0;
while(!found && index < MAX_ELEMENTS){ //this should be !found instead of found
if (table[index].getAbbreviation().equals(abbreviationP)) { // you previously had an assignment statement in this if
found = true;
return table[index]; //This will return the object at the index where it was found.
// Notice I also changed the return type on your function.
}
index++;
}
return null;
}

Data modifies automatically in ArrayList

I have two ArrayLists:
private ArrayList<MenuItemBean> newList= new ArrayList<MenuItemBean>();
private ArrayList<MenuItemBean> newGroupList= new ArrayList<MenuItemBean>();
In one function I am adding data to one ArrayList:
public void setConfirmList(List<MenuItemBean> cList){
newList.addAll(cList);
listAdapter=new ListAdapter(context, newList);
lv_item.setAdapter(listAdapter);
}
Another function where I am just grouping data (increasing quantity if product is already exist) using for-loop and adding data to a second ArrayList. But my problem is as I increase quantity in ArrayList2, my quantity in ArrayList1 itself modifies. I know its because of same reference of objects. Can we change this behavior by any way.
private void groupList() {
newGroupList.clear();
ArrayList<MenuItemBean> mList= new ArrayList<MenuItemBean>();
mList.addAll(newList);
for (int i = 0; i < mList.size(); i++){
String productId = mList.get(i).getProductId();
if(newGroupList.size()==0){
newGroupList.add(mList.get(i));
}else{
Boolean bool=false;
for (int j = 0; j< newGroupList.size(); j++){
if(productId.equalsIgnoreCase(newGroupList.get(j).getProductId())){
bool= true;
// MenuItemBean newObject = new MenuItemBean();
// BeanUtils.copyProperties(newObject, newGroupList.get(j));
MenuItemBean bean= newGroupList.get(j);
int quantity = Integer.parseInt(bean.getUserQuantity());
Double sellingPrice = Double.parseDouble(bean.getSellingPrice());
quantity = quantity + 1;
sellingPrice = sellingPrice * quantity;
bean.setUserQuantity(String.valueOf(quantity));
bean.setUserPrice(String.valueOf(sellingPrice));
newGroupList.set(j, bean);
break;
}
}
if(!bool){
newGroupList.add(mList.get(i));
}
}
}
listAdapter=new ListAdapter(context, newGroupList);
lv_item.setAdapter(listAdapter);
}
I also tried by making copy of ArrayList by using
ArrayList newGroupList= new ArrayList<MenuItem>(newList);
But no help it simple copies data but not the reference. I tried but do not get any example to implement this.
But no help it simple copies data but not the reference.
You're right. By create new list and add data item to new list it's not copy object memory. Both item in those list point to same memory address in heap. So when you modify data item in one of those list. This affects others data item too. for example
public static void main(String[] args) {
List<ObjectItem> datas = new ArrayList<ObjectItem>();
ObjectItem obj1 = new ObjectItem();
obj1.setId(1);
datas.add(obj1);
System.out.println("memory addrs for obj1:" + datas.get(0)); //memory addrs for obj1: 533e846f
List<ObjectItem> other_datas = new ArrayList<ObjectItem>();
other_datas.addAll(datas);
System.out.println("memory addrs for obj1:" + other_datas.get(0));//memory addrs for obj1: 533e846f
}
If you want to solve your problem, let's make deep copy data. For example:
public class ObjectItem {
public ObjectItem(ObjectItem other) {
this.id = other.getId();
}
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
And then using it
List<ObjectItem> new_datas = new ArrayList<ObjectItem>();
for (int i = 0; i < datas.size(); i++) {
new_datas.add(new ObjectItem(datas.get(i)));
}

Need help searching a linked list [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
Hello everyone i have trouble searching a linked list. Basically I'm reading from a csv file and storing it in the linked list. I was able to add the list at the end. But when i search the list it keep saying it wasn't found. The method function is called contains. A method "contains" that takes a Country object as parameter and checks if the name of the country can be found in the list . to check whether object foo of type Country equals objects bar of type Country, you must override the "equals method" in class Country. When I'm running the code it returns not found and i found out the method contains from class countryNode returns null thats why its returns not found. I will appreciate the help thanks. Everything works except from the contains method. Below is my code:
public Country contains(Country obj)
{
if(this.isEmpty())
{
System.out.println("Sorry this is an Empty list");
return null;
}
else{
CountryNode current = first;
while(current!=null)
{
if(current.getCountry().equals(obj))
{
return current.getCountry();
// break;
}
current = current.getNext();
}
return null;
}
}
The class Country and the overrides method equals:
public class Country {
private String countryNames;
private SubscriptionYear[] subscriptions;
private int size;
private int location;
public Country(String country)
{
this.countryNames = country;
}
public Country(String country, int arraylength)
{
this.countryNames = country;
this.size = arraylength;
subscriptions = new SubscriptionYear[size];
location = 0;
}
public void addSubscriptionYear(int year, double subscription)
{
subscriptions[location]= new SubscriptionYear(year, subscription);
++location;
}
public String toString()
{
System.out.print(countryNames+"\t");
for(SubscriptionYear s: subscriptions)
{
//System.out.print(countryNames+"\t");
System.out.print(s.getSubscription()+"\t");
}
System.out.println();
return "";
}
public String getName()
{
return this.countryNames;
}
public boolean equals(Country obj)
{
return (this.countryNames==obj.countryNames);
}
}
This my test main file:
import java.util.Random;
import java.util.Scanner;
public class TestCountryList
{
/**
* Builds a list of countries to debug.
*/
private void debugListOfCountries(Country [] allCountries)
{
// TO COMPLETE
}
/**
* Builds a random list of countries.
*/
private void testRandomListOfCountries(Country [] allCountries)
{
Scanner keyboard = new Scanner(System.in);
System.out.println("How many countries do you want to add to the list?");
int requestedSize = keyboard.nextInt();
// Build the list out of a random selection of countries.
Random random = new Random();
CountryList selectedCountries = new CountryList();
for (int i = 0; i < requestedSize; i++)
{
int selectedIndex = random.nextInt(allCountries.length);
selectedCountries.add(allCountries[selectedIndex]);
}
// Note: To debug your list, comment this line in
System.out.println("List of countries: " + selectedCountries);
// Check if the name of a country is in the list.
// If the country is found, print the details.
// Otherwise output not found.
System.out.println("\nWhat country do you want to search for?");
String countryToFind = keyboard.next();
Country obj = new Country(countryToFind);
Country foundCountry = selectedCountries.contains(obj);
if (foundCountry != null)
{
System.out.println("Country " + countryToFind + " found with details:" + foundCountry);
}
else
System.out.println("Country " + countryToFind + " not found.");
}
/**
* Includes test examples for class GraphView.
*/
public static void main(String[] args)
{
// Create and set objects of type Country
//
final String FILENAME = "data/cellular.csv"; // Directory path for Mac OS X
//final String FILENAME = "data\cellular.csv"; // Directory path for Windows OS (i.e. Operating System)
final int NUM_COUNTRIES_TO_TEST = 3; // Note: Include test cases in addition to 3
// Parse the CSV data file
//
CSVReader parser = new CSVReader(FILENAME);
String [] countryNames = parser.getCountryNames();
int [] yearLabels = parser.getYearLabels();
double [][] parsedTable = parser.getParsedTable();
// Create and set objects of type Country
//
Country [] countries;
countries = new Country[NUM_COUNTRIES_TO_TEST];
Country current;
countries = new Country[countryNames.length];
for (int countryIndex = 0; countryIndex < countries.length; countryIndex++)
{
int numberOfYears = yearLabels.length; // OR numberOfYears = dataTable[countryIndex].length;
current = new Country(countryNames[countryIndex], numberOfYears);
for (int yearIndex = 0; yearIndex < numberOfYears; yearIndex++)
{
double [] allSubscriptions = parsedTable[countryIndex];
double countryData = allSubscriptions[yearIndex];
current.addSubscriptionYear(yearLabels[yearIndex], countryData);
}
countries[countryIndex] = current;
}
TestCountryList application = new TestCountryList();
// Note: Initially, to test your output you may hard code the number of
// countries added, and the array positions selected.
// However, make sure to comment this out before submitting your work.
//application.debugListOfCountries(countries);
application.testRandomListOfCountries(countries);
}
}
Try overriding equals method of Object as below:
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
return (this.countryNames.equals(((Country)obj).countryNames));
}
internally contains call countryList.equals method and equals method's signature is
public boolean equals(Object obj) {}
As opposed to
public boolean equals(Country obj) {}
Also you are just comparing two reference of strings while you need to compare the contents of String. So instead of
this.countryNames==obj.countryNames
You should say:
this.countryNames.equals(obj.countryNames);
you need to use equals or equalsIgnoreCase to compare String
public boolean equals(Country obj)
{
return this.countryNames.equals(obj.countryNames);
}

Why do I keep on getting an ArrayIndexOutofBoundsException?

I am trying to program a program that mimics the actions of a vending machine for my CS class. I have a double array stock that represents the the number of items at a particular "slot" [my vending machine is weird and is kinda like one long vending machine with 1 column of different items]. Here is my code so far:
public class VendingMachine
{
// define fields here
public static double itemPrice[];
public static String[] itemName;
public static int stock[][];
public static int maxPerSlot;
public static double cashAmmount;
public VendingMachine(int numslots, int maxperslot, double cash)
{
final int numSlots = numslots;
maxPerSlot = maxperslot;
cashAmmount = cash;
stock = new int[numSlots][0];
itemPrice = new double[numSlots];
itemName = new String[numSlots];
// complete this method
}
public void setProduct(int slot, String product, double price)
{ int Slot = slot;
itemPrice[slot] = price;
itemName[slot] = product;
stock[Slot][0] = 0;
//
}
public void restockProduct(String product, int quantity)
{
String Product = product;
int currentCapacity = quantity - maxPerSlot;
for(int i = 0; i < stock.length; i++){
if (itemName[i]==Product){
for(;quantity <= maxPerSlot && currentCapacity != 0; quantity--)
stock[i][0] += 1;
}
}
//Put # of products in slot that holds it and if that slot is full put the rest in the next
//availble slot that holds that product, if all full return error.
}
public double getCashOnHand()
{
return cashAmmount; // replace this line with your code
}
public int getQuantity(int slot)
{
return stock[slot][1]; // replace this line with your code
}
public int getQuantity(String product)
{ int total = 0;
for (int i = 0; i<itemName.length;i++){
if (product == itemName[i]){
total += stock[i][1];
}
}
return total;
}
public boolean buyItem(int slot)
{ int snum = slot;
if (stock[snum][1] != 0){
stock[snum][1]--;
return true;
} else {
return false;} // replace this line with your code
}
}
Every time I runException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at VendingMachine.setProduct(VendingMachine.java:27)
at vmd.main(vmd.java:9) this code though I get this error message:
Can someone here please explain to me why I continue to get this error? I mean the logic seems quite correct .
Your problem's here:
stock = new int[numSlots][0];
This defines an array of numSlot arrays with a length of 0 each.
when you initialize stock in the constructor do this instead:
stock = new int[numSlots][1];
using 0 instead of 1 initializes an array of length 0!
You allocate zero elements in the second dimension of stock,
stock = new int[numSlots][0];
so you get that exception when you try to access the element at index zero.
stock[Slot][0] = 0;
This line
stock = new int[numSlots][0]; // <-- A length of zero? You want a one there.
Should be
stock = new int[numSlots][1]; // <-- like so. Or, if you really don't
// want to change your other code make it a 2.
// But you'll leave memory unused, and you really should change it.
Everywhere else (where you have code like this) -
stock[slot][1] // <-- stock[INDEX][1] <--- should be 0.
Like this
stock[slot][0] // <-- all of the other accesses.
Because this line:
stock = new int[numSlots][0];
allocates stock to be an array of arrays, and each of those arrays has length 0. So you can't assign anything into those arrays (they don't have any elements to assign). So when you do this:
stock[Slot][0] = 0;
you will get an ArrayIndexOutOfBounds. Remember that in Java, indexes start at 0, so if you want an array where the indexes go from 0 to N, you have to allocate the array with size N+1.

Categories

Resources