I am designing a new cinema booking system, where there will be 4 screens holding various number of seats on each.
I need to know what ARRAY or what data structure is best for ADDING and REMOVING people onto or off seats ANYWHERE they want on the screen.
I believe that I will need a 2 dimentional array structure, but any help will be much appreciated!... thank you
What you should do is build a class structure that will abstract out the way you are storing the data in memory. You might do something like:
class Cinema {
List<Auditorium> screens;
}
class Auditorium {
int number;
List<SeatRow> rows;
}
class SeatRow {
int rowNumber
List<Seat> seats;
}
class Seat {
int seatNumber;
boolean occupied;
}
Note: This isn't the only solution. You may want to look into storing Seats in a Map or some other data structure.
ArrayList is a nice simple array type list that permits adding and removing.
You could create an array of arrays if you like. That would be a 2 dimentional array.
Sounds like 4 instances of the same data structure. Possibly a Collection of Screen objects that contain a Collection of seats.
I'd vote personally for a plain and simple Seat[][] array of the class structure suggested above. There's simply no reason to use another array as the array size probably isn't ever going to change, if it is that can be done at initialisation. Then just show them or don't on the screen by either data in a certain position or null for unreserved seats.
Depending on your need (do you need to remember where the guest booked?) you could even use boolean[][] as the bare minimum.
No matter what, just create and name four different such Seat 2D arrays. Preferably stick them in a separate class and have setters and getters.
Related
I'm a Java newbie with a quick Array vs. ArrayList question. I have an array of objects that can grow or reduce in size, but it's very important for me to maintain the position they were in relative to each other in the array. I'm thinking because of this I need to use Array instead of an ArrayList which can condense/shift elements around if they are removed/added.
The practical example: In my first Java application that I'm slugging through to learn the nuances of this language I'm making a basic poker game simulator. I have Player objects in an array representing the seats they are sitting at, and it's important to know where the dealer button (index) was placed before rotating it. Players being removed or added from an ArrayList will change the indices of the players, and that can throw off the next Player to get it. Dealer button movement is very player-placement specific.
Long story short - is using an Array the best way of handling elements in an array-type structure that need to maintain their position in the array? Is there a better method or logic to accomplish this? I apologize for the simple question but I couldn't find any other alternatives and wanted to confirm that this is the best route to take.
EDIT:
To further clarify, let me give an example of why ArrayList's element movement won't work:
Take three players and their indices in the array:
0 : Player One (Dealer button)
1: Player Two
2: Player Three
If player two (index one) gets up from the table before the dealer button is rotated, depending on the rules player one will keep the button and the blinds will be adjusted accordingly (there's other variants of this rule, but the one I like to use). In an ArrayList, the internal array will be condensed and player three will end up getting the button an extra round before he should. I need to track the empty seat that was active during the hand but was emptied before the round was over and the button moved.
I'm starting to realize that the concept of a "seat" is going to be more complicated, I need to track state on it, including "player just sat down while hand in progress," "player got up while hand in progress," etc. #Stephen P - I think you're right about this, I'm going to need to track them separately and cannot use a simple array structure to determine the logic. Timing of when the elements are added and/or removed is paramount to the application logic, and simply examining if an element is there or not won't cut it.
For the Seats themselves, I'm learning towards ArrayList since the Seats will now always be there, no empties. The Seat will just have a reference to the Player object if one is sitting there as well as WHEN that player arrived. Thanks everyone!
With ArrayList, you can make your players sit tight by using set(int index, T value). You just have to fill the arrayList with nulls first:
List<Player> seats = new ArrayList<>(Collections.nCopies(numPlayers,(Player)null));
seats.set(2,player); // Place a player in the third chair
seats.set(1,null); // Empty the second chair
Long story short - is using an Array the best way of handling elements
in an array-type structure that need to maintain their position in the
array? Is there a better method or logic to accomplish this? I
apologize for the simple question but I couldn't find any other
alternatives and wanted to confirm that this is the best route to
take.
Position shouldn't be your most important criterion for choosing array vs. ArrayList, at least I don't believe it should be.
Arrays are covariant, and more performant most of the time. They mix poorly (if at all) with Java generics which is really kind of a big deal a lot of the time. You cannot create a reference to a new instance of an array of a non-reifiable type (though you can receive one, but buyer beware).
ArrayLists, as a part of the Java Collections API, are invariant. For this reason they work much better with Java generics and, according to Joshua Bloch (Essential Java, 2nd Ed), should be favored much of the time. ArrayLists should often be less performant (and less concise) than arrays. Moreover, as part of the Java Collections API, ArrayLists are more flexible because they extend the List interface which enables you to change implementations from ArrayList to any other List provided that your own class that implements the List is well encapsulated (i.e. the ArrayList is not part of your class's exported API).
There are other differences, of course, but these are the ones that really stand out. If you were really concerned about performance, you could create your own List implementation that was backed by arrays (like ArrayList is) in order to get a feature or the API contract you really wanted. Otherwise, to me, it sounds like you should be using ArrayList (or even other Collection type such as Map (suggested)).
If you have a constant number of seats, you can use either an array or an ArrayAist. If you want to increase the number of seats, you will need an Arraylist, because regular arrays are immutable. See this for more information on the immutability of arrays: Why is an array's length immutable? An ArrayList will never move around its contents if you only use the get(int index) and set(int index, E element)
Also, it is bad practice to let null mean something, even if that something is nothing.
The code:
seat ArrayList initialization
List<Person> seats = new ArrayList<Person>(max_Number_Of_Seats_here);
for(Person person : seats)
{
person = new Person("");
}
//You can then set people like this:
seats.set(seat_index_here, new Person("Darkprozac"));
And have the parameter for the constructor for the class Person be its name.
Person constructor
...
public String name;
public Person(String name)
{
this.name = name;
...
You can then check if the Person's name is "", and if it is, skip that person:
Check if seat is empty
...
for(Person person : seats)
{
if(person.name.equals(""))
{
//do nothing
}
else
{
doSomething();
}
}
...
You can also wrap a Person in a Seat class:
Seat Class
public class Seat
{
public Person person;
public String state;
public Seat(String name)
{
if(name.equals("");
{
state = "empty";
}
else
{
state = "full";
person = new Person(name);
}
}
}
and then modify seat ArrayList initialization and Check if seat is empty accordingly.
Thanks to MrBackend for pointing out that I was wrong about ArrayLists initializing as null.
I would use a map, specifically, a TreeMap.
NavigableMap<Integer, Player> seats = new TreeMap<Integer, Player>();
Integer first = seats.firstKey();
Integer next = seats.nextKey(first);
This gives the benefits of a map, you don't have to worry about seats shifting (even accidentally), and you can still navigate seats easily.
The map manages its own storage (unlike an array) and does not have a risk of shifting indices (unlike an ArrayList).
This is sort of an follow up to the first post I made, lets say I got two classes:
public class Carinfo {
private String carname;
//The Carinfo[] value is set when making a new car
//so for the object ford the array holds 3 null pointers
private Carinfo [] value;
Carinfo (String someCar, int carValue) {
this.carname = someCar;
this.value = new Carinfo[carValue];
}
}
And the second class:
public class CarPark {
HashMap<String, Carinfo> carGarage;
CarPark() {
carGarage = new HashMap<String, CarInfo>();
Carinfo ford = new Carinfo("Ford", 3);
Carinfo audi = new Carinfo("Audi", 2);
carGarage.put("Ford", ford);
carGarage.put("Audi", audi);
}
}
So let's say for whatever reason I want the object ford who has 3 null pointers
in its Carinfo array, to point at the object audi.
Meaning I can go through the Carinfo objects and list the pointers each car
has to other cars.
Think of it as a family, I want to see what cars are related to each other.
I am having a hard time creating a method that will point to other objects
in my Carinfo HashMap.
Any "pointers"? If anything is unclear please let me rephrase or try to explain it better.
Cheers
I don't really understand what you're trying to do. One way to realize that is to provide a specific method to add a relation. For example, with your array you could do that:
public class CarInfo {
private Carinfo[] value;
public void addCarInfo(CarInfo carInfo, int position) {
value[position] = carInfo;
}
}
Anyway, it is not a good idea to have an array, you should use a List.
I would recommend not storing the relationships between cars inside the Carinfo objects themselves. Instead, you should use a general-purpose graph library (or write your own general-purpose graph library).
As you probably know, a graph is a set of nodes and edges, and each edge represents a relationship between two nodes. The notion that your current code describes is really just a directed graph: each car is a node, and each car can hold some number of references to the other cars, where each reference represents an edge pointing out from that car.
Graphs are such a common abstraction in math and computer science that plenty of libraries have been implemented to represent graphs, with the side benefit that several popular problems are solved for any code that uses the libraries (for instance, finding a multistep relationship between two cars using the fewest number of edges, or finding the smallest number of edges needed in the graph to ensure that all the cars are still indirectly connected). I would recommend searching for already-implemented graph libraries, and then using the one with the best features for your overall problem. If this is a homework assignment, though, you should probably implement your own graph library. This isn't too hard: you need to store nodes and edges somehow (you can just keep a list of nodes, and you could use an edge list or adjacency matrix to store edges), and you will need to provide the algorithms you care about in a somewhat more general form. This may seem like more work, but the benefits of making your code more modular will pay off quickly. You'll create fewer bugs in the first place, since each part of your code performs only one job, and you'll be able to fix bugs more easily and quickly, probably saving you time overall.
For starters you'll need accessing methods on your CarInfo object in order to play with the value array you've set up.
public CarInfo[] getCarValue() {
return value;
}
Now, when you're playing in a method you can call it as follows:
CarInfo[] fordValueArray = carGarage.get("Ford").getCarValue();
This array now points to the one you created on the 3rd command of CarPark().
With that we can do:
fordValueArray[0] = audi;
Now, that all said, it seems a little unclear why you'd set up a class relation like this. The naming of value is seemingly non-intuitive because at face value what you've asked is how we can have a car's value relate to a number of other cars independantly. Ford's first value is an Audi? What are the other two values? Why would we be limited to 3 at all?
I currently have 3 arrays of information and am unsure of how to sort them based on one of the values:
int[] rank = { 1, 3, 4, 2, 5 };
String[] game = { "Snake", "Mines", "Fragged", "Siege", "Tower" };
int[] year = { 1980, 1983, 1981, 1995, 1992 };
I'm wanting to sort it by rank, and I've seen many examples of people using comparators to sort 2 parallel arrays, but I haven't seen any example for sorting more than 2.
My first thought was to create a class with a variable for each and then sort that object, but is an extra class really necessary for a sort?
My first thought was to create a class with a variable for each and then sort that object, but is an extra class really necessary for a sort?
It's not strictly necessary - you could definitely write some code to avoid it if you really wanted to. However, I'd say it's a thoroughly good thing.
You don't really have three collections of separate items here: you have one collection of items, each of which has three properties. So make your code match that. Whenever you find you have parallel collections, such that a[0] is related to b[0] is related to c[0] etc, you should think about encapsulating that information in a separate class. It will make your code much easier to maintain, and enforces more consistency.
For example, it would make no sense for those arrays to have different lengths: but there's nothing inherent in the declaration to stop that. If you have one collection, you can't possibly have different numbers of items for the different properties, precisely because you've got one collection.
I think creating a new class would be the cleanest solution. You could manually implement a new sort function to duplicate swaps to the other 2 arrays whenever you apply a swap to the first array (rank), but that gets messy very quickly.
Something like the following would be all you need:
public class Game implements Comparable<Game>{
private int rank = 0;
private int year = 0;
private String name = "";
...
// Constructor +
// Usual getters and setters here
..
public int compareTo(Game anotherGame) {
return this.rank - anotherGame.getRank();
}
}
And then you can simply do:
List<Game> games = new ArrayList<Game>();
...
// Add some games to your games list
...
Collections.sort(games);
Is the extra class necessary? Well no, of course not. You could come up with a sorting routine that would keep everything consistent. However, what happens if next week you decide you need a 4th array, such as a publisher? Now your sorting routine won't work and you have to write a new one.
If you instead write a class to hold these fields as properties, you can simplify the sorting logic immensely, plus you only have to worry about one array. Any extra work you do now will be recouped very quickly then next time you have to maintain this code.
i am looking for a data structure to store two dimensional integer arrays.
Is List the rigth data structure or should i use another one?
Can someone give me a short example on how to create such a data structure and how to add a 2d array?
Edit: I want a data structure in which i want to store int[11][7] arrays.
For instance ten, int[11][7] arrays.
If you need to store a number of int[][] arrays in a data structure, I would probably recommend that you store the int[][] arrays in an Object that represents what the data contains, then store these Objects in an ArrayList.
For example, here is a simple Object wrapper for your int[][] arrays
public class 2DArray {
int[][] array;
public 2DArray(int[][] initialArray){
array = initialArray;
}
}
And here is how you would use them, and store them in an ArrayList
// create the list
ArrayList<2DArray> myList = new ArrayList<2DArray>();
// add the 2D arrays to the list
myList.add(new 2DArray(myArray1));
myList.add(new 2DArray(myArray2));
myList.add(new 2DArray(myArray3));
The reason for my suggestion is that your int[][] array must have some meaning to you. By storing this in an Object wrapper class, you can give it a meaning. For example, if the values were co-ordinates, you would call your class Coordinates instead of 2DArray. You, therefore, create a List of Coordinates, which has a lot more meaning than int[][][].
An array is not just an idea about how to store information, it is also an implementation of how to store data. Thus, if you use an array, you have already selected your data structure.
If you want to store data in a data structure, you need to concentrate on how the data structure is used, think about how you will retrieve data and store data, how often you do each operation, and how much data you will be working with. Then you know which methods must be optimum, and have an idea of whether the data can reside in memory, etc.
Just to give you an example of how many ways this could be solved:
You could flatten the array into a 1D array, and use x*num_columns+y as the index
You could create an Object to contain the pair, and put the array in a Map
You could use a linked list containing linked lists.
You could use a tree containing trees.
You could use a list containing trees.
You could create a partial order over the pair and then put all the elements into one tree.
All of these solutions depend heavily on which operations are more important to optimize. Sometime it is more important to update the data structure quickly, sometimes not. The deciding factor is really the rest of your program.
So you want to store a collection of 2D arrays: if the collection is fixed size add another dimension:
int[][][] arrColl
If the collection is variably sized, use your favorite implementation of Collection<int[][]> (ArrayList, LinkedList, etc.):
Collection<int[][]> arrColl
based on your edits :
List<Integer[][]> is what you need - this will allow you to add any numbers of 2D Integer arrays. Note that this will involve boxing and unboxing - something that should be avoided if possible.
If it suffices ( if you know how many 2D int arrays you need in advance ), you can even use int[][][] - a 3D array of ints - this does not involve boxing/unboxing.
If size is fixed, then use int[][] else List<List<Integer>>.
Although I have Java in the title, this could be for any OO language.
I'd like to know a few new ideas to improve the performance of something I'm trying to do.
I have a method that is constantly receiving an Object[] array. I need to split the Objects in this array through multiple arrays (List or something), so that I have an independent list for each column of all arrays the method receives.
Example:
List<List<Object>> column-oriented = new ArrayList<ArrayList<Object>>();
public void newObject(Object[] obj) {
for(int i = 0; i < obj.length; i++) {
column-oriented.get(i).add(obj[i]);
}
}
Note: For simplicity I've omitted the initialization of objects and stuff.
The code I've shown above is slow of course. I've already tried a few other things, but would like to hear some new ideas.
How would you do this knowing it's very performance sensitive?
EDIT:
I've tested a few things and found that:
Instead of using ArrayList (or any other Collection), I wrapped an Object[] array in another object to store individual columns. If this array reaches its capacity, I create another array with twice de size and copy the contents from one to another using System.copyArray. Surprisingly (at least for me) this is faster that using ArrayList to store the inner columns...
The answer depends on the data and usage profile. How much data do you have in such collections? What is proportions of reads/writes (adding objects array)? This affects what structure for inner list is better and many other possible optimizations.
The fastest way to copy data is avoid copying at all. If you know that obj array is not modified further by the caller code (this is important condition), one of possible tricks is to implement you custom List class to use as inner list. Internally you will store shared List<Object[]>. Each call we just add new array to that list. Custom inner list class will know which column it represents (let it be n) and when it is asked to give item at position m, it will transpose m and n and query internal structure to get internalArray.get(m)[n]. This implementation is unsafe because of limitation on the caller that is easy to forget about but might be faster under some conditions (however, this might be slower under other).
I would try using LinkedList for the inner list, because it should have better performance for insertions. Maybe wrappping Object arra into collection and using addAll might help as well.
ArrayList may be slow, due to copying of arrays (It uses a similar approach as your self-written collection).
As an alternate solution you could try to simply store the Rows at first and create columns when neccessary. This way, copying of the internal arrays at the list is reduced to a minimum.
Example:
//Notice: You can use a LinkedList for rows, as no index based access is used.
List<Object[]> rows =...
List<List<Object>> columns;
public void processColumns() {
columns = new ArrayList<List<Object>>();
for(Object[] aRow : rows){
while (aRow.size() > columns.size()){
//This ensures that the ArrayList is big enough, so no copying is necessary
List<Object> newColumn = new ArrayList<Object>(rows.size())
columns.add(newColumn);
}
for (int i = 0; i < aRow.length; i++){
columns.get(i).add(aRow[i]);
}
}
}
Depending on the number of columns, it's still possible that the outer list is copying arrays internally, but normal tables contains far more rows than columns, so it should be a small array only.
Use a LinkedList for implementing the column lists. It's grows linearly with the data and is O(1). (If you use ArrayList it has to resize the internal array from time to time).
After collecting the values you can convert that linked lists to arrays. If N is the number of rows you will pass from holding 3*N refs for each list (each LInkedList has prevRef/nextRef/itemRef) to only N refs.
It would be nice to have an array for holding the different column lists, but of course, it's not a big improvement and you can do it only if you know the column count in advance.
Hope it helps!
Edit tests and theory indicate that ArrayList is better in amortized cost, it is, the total cost divided by the number of items processed... so don't follow my 'advice' :)