I'm pretty new to the world of coding and I have a problem.
I'm creating a simple java class that reads strings from an array but every time I run the program, I get a "null" in my very first element.
This is my code:
public class Airline {
/* Fields */
private String name;
private String[] list;
private int size = 0;
private int DEFAULT_SIZE = 1;
/* Constructor */
public Airline() {
list = new String[DEFAULT_SIZE] ; // creates an airline array
}
/* Methods */
// method that adds "airline name" into the array
public void add(String name) {
this.name = name;
//a new array with + 1 index
String[] temp = new String[list.length + 1];
//copy items from list[] to temp[]
for (int i = 0; i < list.length; i++) {
temp[i] = list[i];
}
// add the last integer to new temp
temp[temp.length - 1] = name;
list = temp;
}
// method that reads from the array start
public int read(int read) {
for (int i = 0; i < list.length; i ++) {
Airline temp = new Airline();
System.out.println("Airline: " + list[i]);
}
return size;
}
And this is my test class:
public class TestAirline {
public static void main(String[] args) {
//create the object
Airline airline = new Airline();
// add airline names
airline.add("Air Canada");
airline.add("West Jet");
airline.add("Sunwing Airlines");
airline.add("Air Transat");
airline.add("Emirates");
airline.add("Cathay Pacific");
airline.add("Etihad");
airline.add("British Airways");
airline.add("Delta Airlines");
airline.add("United Airlines");
airline.add("American Airlines");
airline.add("Porter Airlines");
//read the array
airline.read(0);
}
But this is my output, I get a "null" in my very first element and I don't know why
Airline: null
Airline: Air Canada
Airline: West Jet
Airline: Sunwing Airlines
Airline: Air Transat
Airline: Emirates
Airline: Cathay Pacific
Airline: Etihad
Airline: British Airways
Airline: Delta Airlines
Airline: United Airlines
Airline: American Airlines
Airline: Porter Airlines
It's because you start with a list of length 1.
When you create an array in Java, its elements are initialized to the default value for the type; for objects, that's null. So, you start off with an array containing null.
When you call add, you append the new string to the end of the list; but you never overwrite elements, so that null is not overwritten.
Set DEFAULT_ZERO to zero, and you won't have this null in the array initially.
You should strongly consider using an ArrayList instead of manually resizing the array like this. At the very least, you should read about ArrayList's resizing strategy, which is to double in length when you run out of space. Resizing by 1 each time is very inefficient.
That is because you do
temp[temp.length - 1] = name;
Where temp.length is already at 2.
Which means you write name in temp[1] instead of temp[0]
As others answers pointed, you should use ArrayList. But if you want to build it yourself for learning purpose...
public class Airline {
/* Fields */
private String name; //This is useless as you never really need it
private String[] list;
private int size = 0; //This is useless as you never really use it
private int DEFAULT_SIZE = 1; //This is useless as you never really need it
/* Constructor */
public Airline() {
// list = new String[DEFAULT_SIZE] ;
/* The line above is useless as you are wasting space. If you want to use an array, then you should initialize it only when you want to put the first element inside. */
}
/* Methods */
// method that adds "airline name" into the array
public void add(String name) {
/* The argument name already hold the "name" of the latest airline */
//this.name = name;
//a new array with + 1 index
//Just check if list is null here
if(list==null) list = new String[1]; list[0] = name;
else {
String[] temp = new String[list.length + 1];
//copy items from list[] to temp[]
for (int i = 0; i < list.length-1; i++) {
temp[i] = list[i];
}
// add the last integer to new temp
temp[temp.length - 1] = name;
list = temp;
}
}
// method that reads from the array start
public int read() {
//Notice you don't need the argument read as you always read from the start, if you wanted to read from the index read, replace i=0 below by i=read and add the argument
for (int i = 0; i < list.length; i ++) {
Airline temp = new Airline(); //And as far as I know, you don't need this too
System.out.println("Airline: " + list[i]);
}
return size;
}
Related
I have an arraylist that looks like this:
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
I store groups of 2 persons in a pair. For example:
[Person1, Person2]
[Person3, Person4]
The algorithm I use right now still makes duplicates, I've tried out hashmaps and iterating through them with for loop but they just give me back the original list.
This is the code:
package com.company;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class createGroups
{
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
public static void main(String[] args){
//Define names
String[] names = {"Person1", "Person2", "Person3", "Person4"};
try
{
//Create combinations. In a try catch because of the saveFile method.
combination(names, 0, 2);
//Print all the pairs in the Arraylist x
printPairs();
} catch (IOException e)
{
e.printStackTrace();
}
}
static void combination(String[] data, int offset, int group_size) throws IOException
{
if(offset >= data.length)
{
//Create new Arraylist called foo
ArrayList<String[]> foo = new ArrayList<>();
//Create a pair of 2 (data.length = 4 / group_size = 2)
for(int i = 0; i < data.length / group_size; i++)
{
//Add the pair to foo.
foo.add(Arrays.copyOfRange(data, 2 * i, 2 * (i + 1)));
}
//Add foo to x
x.add(foo);
//saveFile(foo);
}
for(int i = offset; i < data.length; i++){
for(int j = i + 1; j < data.length; j++){
swap(data, offset, i);
swap(data, offset + 1, j);
combination(data, offset + group_size, group_size);
swap(data, offset + 1, j);
swap(data, offset, i);
}
}
}
public static void printPairs(){
//Print all pairs
for(ArrayList<String[]> q : x){
for(String[] s : q){
System.out.println(Arrays.toString(s));
}
System.out.println("\n");
}
}
private static void swap(String[] data, int a, int b){
//swap the data around.
String t = data[a];
data[a] = data[b];
data[b] = t;
}
}
The output right now is this:
Output
Every group of 4 names is a 'list' of pairs (Not really a list but that's what I call it)
And this is the desired output:
Desired output
But then you can see that the first and the last list of pairs are basically the same how do I change that in my combination method
The question:
How can I change my combination method so that it doesn't create duplicate groups.
And how can I make the list smaller (The desired output) when printing the created lists.
If I wasn't clear enough or if I didn't explain what I want very well, let me know. I'll try to make it clearer.
Create an object similar to this. It takes 4 strings (2 pairs). Puts the strings into array and sorts this array. That means any combination of strings you put in will be converted into one sorted combination, but the object internaly remembers which person is person1, person2, ...
private class TwoPairs {
private final String person1;
private final String person2;
private final String person3;
private final String person4;
private final String[] persons;
TwoPairs(String person1, String person2, String person3, String person4) {
this.person1 = person1;
this.person2 = person2;
this.person3 = person3;
this.person4 = person4;
persons = new String[4];
persons[0] = person1;
persons[1] = person2;
persons[2] = person3;
persons[3] = person4;
// if we sort array of persons it will convert
// any input combination into single (sorted) combination
Arrays.sort(persons); // sort on 4 objects should be fast
// hashCode and equals will be comparing this sorted array
// and ignore the actual order of inputs
}
// compute hashcode from sorted array
#Override
public int hashCode() {
return Arrays.hashCode(persons);
}
// objects with equal persons arrays are considered equal
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
TwoPairs other = (TwoPairs) obj;
if (!Arrays.equals(persons, other.persons)) return false;
return true;
}
// add methods which you might need
// getters for individual persons
// String getPerson1() { return person1; }
// or perhaps pairs of persons
// String[] getPair1() { return new String[] {person1, person2}; }
// add sensible toString method if you need it
}
Your ArrayList x will change like this
ArrayList<TwoPairs> x = new ArrayList<TwoPairs>();
before adding new TwoPairs object into x check if this list already contains this object.
if (!x.contains(twoPairsObject)) {
x.add(twoPairsObject);
}
I am trying to create an ArrayList from a given array. This is the array I have:
public class Warehouse
{
private final static int MAX = 60;
private Item [] stock;
private int numItems;
public Warehouse()
{
stock = new Item[MAX];
numItems = loadData();
}
Now where should I change the processing from an array to an arraylist? Is this supposed to be done in the constructor or somewhere else? Thanks.
Why not use this?
List<Item> stockList = Arrays.asList(stock);
Just keep a separate class for the array and within the class that you want to get that specific array you can create an ArrayList Object.
public class ArrayaData {
public int Id;}
And the within the next class,
public class ClassYouWant {
ArrayList<ArrayaData> arrayList ;
}
and when ever you want to add a value to that array just create a new instance and then save it.
arrayList = new ArrayList<ArrayaData>();
arrayList.Id = "Value you want.."
arrayList = new ArrayList<ArrayaData>();
arrayList.Id = "Value 2 you want.."
Or you can simply set it in a Loop as well,
int arraySize = 5; //Size of the array you want
for (int i = 0; i < arraySize; i++) {
arrayList = new ArrayList<ArrayData>();
arrayList.Id = "Value you want";
}
And to get the vlaues you can use a Loop also,
int arraySize = arrayList.size(); //Size of the created arrayList
int value;
for (int i = 0; i < arraySize; i++) {
value = arrayList.get(i);
Toast.makeText(this, "Value " + i + ":" + value, Toast.LENGTH_SHORT).show();
}
Hope this helps..
I have defined a class Note that represents a way to play a certain note (two integers for the string and fret on a string instrument), and a class Chord which has an ArrayList of all the notes in that chord.
For every note that is played there may be multiple ways of playing that note so I have an ArrayList of Notes representing each possible way. In a chord there can be any number of notes so I have an ArrayList of ArrayLists of Notes. From this I want to create an ArrayList of chords with each possible way of playing the chord.
I have defined a constructor Chord(ArrayList<Note> notes)
eg:
Note A has 3 ways of being played and note B 2 ways of being played, from this I would want chords with:
[A1,B1], [A1,B2], [A2 B1], [A2 B2], [A3,B1], [A3,B2].
I have created a method that works under the assumption that there are always 3 notes played but can't think how to expand it to work for an unknown number
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
ArrayList<Chord> allPlayable = new ArrayList<>();
for (int i = 0; i < candidates.get(0).size(); i++)
{
Note n0 = candidates.get(0).get(i);
for (int j = 0; j < candidates.get(1).size(); j++)
{
Note n1 = candidates.get(1).get(j);
for (int k = 0; k < candidates.get(2).size(); k++)
{
Note n2 = candidates.get(1).get(k);
ArrayList<Note> chordNotes = new ArrayList<>();
chordNotes.add(n0);
chordNotes.add(n1);
chordNotes.add(n2);
allPlayable.add(new Chord(chordNotes));
}
}
}
return allPlayable;
}
IT was suggested to me to use recursion - every for loop would be another recursive call and I came up with this answer
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
//this will be the inner ArrayList we are on
ArrayList<Note> current = new ArrayList();
//the list of chords to return
ArrayList<Chord> allPlayable = new ArrayList();
allPlayableRecurse(candidates, 0, current, allPlayable);
return allPlayable;
}
public static void allPlayableRecurse(ArrayList<ArrayList<Note>> candidates, int index, ArrayList<Note> chordNotes, ArrayList<Chord> allPlayable)
{
ArrayList<Note> current = candidates.get(index);
//for each note in the current array list of notes
for (int i = 0; i < current.size(); i++)
{
chordNotes.add(current.get(i));
//there are more notes to add
if (index < candidates.size()-1)
{
//go to the next inner ArrayList
allPlayableRecurse(candidates, index+1, chordNotes, allPlayable);
}
else//we have reached the last note
{
//add the chord to the list
allPlayable.add(new Chord((ArrayList<Note>)chordNotes.clone()));
}
//we will now replace this note
chordNotes.remove(chordNotes.size()-1);
}
}
You could use recursion, for example:
List<List<Note>> combine(List<List<Note>> representations) {
List<Note> options = representations.get(0);
List<List<Note>> tails;
if (representations.size()==1) {
tails = new ArrayList<>();
tails.add(Collections.emptyList());
} else {
tails = combine(representations.subList(1, representations.size()));
}
List<List<Note>> combinations = new ArrayList<>(options.size());
for (Note note : options) {
for (List<Note> tail : tails) {
List<Note> chord = new ArrayList<>();
chord.add(note);
chord.addAll(tail);
combinations.add(chord);
}
}
return combinations;
}
public List<Chord> allPlayable(List<List<Note>> candidates) {
List<List<Note>> combinations = combine(candidates);
List<Chord> chords = new ArrayList<>(combinations.size());
for (List<Note> notes : combinations) chords.add(new Chord(notes));
return chords;
}
It is the old java7 style. It can be done easier with new Java8 functional operations but not sure if it is already your thing if you just started.
I have an array of objects. When the array fills up, I want to make a new array twice as large as the old one, and transfer all the elements over. I'm doing something wrong, I think its something to do with I'm not creating the correct reference to the new array. Here's my code, any help figuring this out would be appreciated.
private int DIRECTORY_SIZE = 6;
Entry [] directory = new Entry[DIRECTORY_SIZE];
private int numberOfElements = 0;
public int getNumOfElements(){
return numberOfElements;
}
public void setDirectorySize(int size){
DIRECTORY_SIZE = size;
}
public int getDirectorySize(){
return DIRECTORY_SIZE;
}
public void addEntry(String surname, String initial, String num) {
// TODO add an entry to an array, also increments numberOfElements variable tracking whats in array
if(getNumOfElements() == getDirectorySize()){ // if array is full
doubleArraySize(); // put temp values into new bigger directory array
}
int i = findFreeLocation();
directory[i] = new Entry(surname, initial, num);
numberOfElements++;
}
private void doubleArraySize(){
Entry[] temp = new Entry[DIRECTORY_SIZE]; //make new temp array same size as old one
for(int i = 0; i < DIRECTORY_SIZE ; i++){
temp[i] = directory[i]; // cycle through array putting all values into temp
// works up to here
}
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
for(int i = 0; i < temp.length ; i++){
directory[i] = temp[i];
}
}
private int findFreeLocation() {
int i;
for (i = 0; i < DIRECTORY_SIZE; i++)
{
if(directory[i] == null)
{
break;
}
}
return i;
}
In doubleArraySize() function , this is the issue :
Entry[] directory = new Entry[DIRECTORY_SIZE];
// you are not assigning it to the class attribute directory
// instead you are creating a local array directory
Make the following change :
this.directory = new Entry[DIRECTORY_SIZE];
// this will assign the newly created array to the class attribute
Note : I personally prefer to use this pointer to refer to class attributes so that it makes my code more readable, and its clear to everyone that the variable in question is a class attribute rather than local variable.
**SIZE has already double by this point. No need to multiple by 2
I remember doing something exactly like this when I was making a Vector ADT. However, I used instance variables instead of methods in my code for element number and the capacity. I definitely didn't initialize a Vector inside a method for a Vector.
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
Isn't DIRECTORY_SIZE an instance variable? Because if it is, I don't think you can initialize an object using an instance variable from the object you are overwriting.
Putting my code into your context, it would look something like this:
private void doubleDirectorySize()
{
Entry[] new_array = new Entry[new_directory_size*2];
for (int i = 0; i < directory_size; i++)
{
new_array[i]= directory[i];
}
directory= new_array;
}
This only works if directory was initialized to null, though, moving the pointer directory to the new array.
I've gotten the basics of insertion code but I'm stuck on how to compare it with another condition other then (list by A-Z, Z-A)
for the example a list of staff ranks were given :
public static final String[] staffrank = {
"Trainee",
"Junior",
"Senior",
"Administrator"
};
I have a method to compareRank
If it returns 0 means they're of equal rank (staff 1 and staff 2)
if it returns -1 means staff 1 is lower rank than staff 2
if it returns 1 means staff 1 is higher rank than staff 2
Then I have a list of staffs in void main
Staff[] snames;
int countname=0;
snames = new Staff[50];
snames[countname++] = new Staff("Amy","Trainee");
snames[countname++] = new Staff("Annie","Junior");
snames[countname++] = new Staff("Tom","Administrator");
snames[countname++] = new Staff("Dave","Trainee");
snames[countname++] = new Staff("Gary","Junior");
snames[countname++] = new Staff("Donna","Senior");
then the insertion sort compare code
public static void insertionSortbyRank(Staff[] snames, int countname) {
//insertion sort
for(int i =1; i < countname; i++) {
int j = i;
int comparerank = Staff.compareRank(snames[j],snames[j-1]);
String name = snames.getName();
String rank = snames.getRank();
//if staff is lower rank
if(comparerank==-1) {
Then i'm unsure what to put in this while loop
still giving me an unsorted list
while( j >0 && rank.compareRank(list[j], list[j - 1]) == 1))) {
list[j].rank =[j-1].rank;
list.[j].name = [j-1].name;
j--;
}
then the end is replacing the new values
snames[j].name = name;
snames[j].rank = rank;
the output suppose to give : (by order of their ranks from low to highest according to the chart)
Amy, Trainee
Dave, Trainee
Annie, Junior
Gary, Junior
Donna, Senior
Tom, Administrator
Any help would be appreciated..thank you
I would assume that since you've been given a staffrank variable, that you should probably make use of it. However, aside from mentioning it at the top of your question, you make no other use of it that we've been shown...So my assumption is that you've ignored it completely.
I think that's the key to your puzzle here.
Note that I'm ignoring the fact that String arrays are not the best representation (I'd go for an enum or something like a class...Potentially implementing Comparable<StaffRank> somewhere...But this is a test question as noted, after all...)
You could make a function like this:
public static final int compareRank(String[] ranks, String rank) {
for (int i=0; i<ranks.length; i++) {
String string = ranks[i];
if string.equals(rank) return i;
}
return -1;
}
Which will return an integer between -1 and (ranks.length -1) which you can use for comparison. The smaller the number the more junior the rank.
Inside your while loop you'll have to compare each staff and swap them if the "i"-th staff is greater than the "i+1"-th staff.
for (int i=0; i<(snames.length-1); i++) {
Staff sname1 = sname[i];
Staff sname2 = sname[i+1]
//compare sname1 to sname2 and swap if sname1 > sname2
}