Setting a Maximum limit for an ArrayList - java

So for school I am making a program where we are creating a booking system where people can book a ticket for a movie that has a capacity of 10 people. People are allowed to change the time of the booking to the next day as long as the theater is not full for that day.
An array will be no good in this situation as I need to be able to remove an object from the array and make another free space in said array, and then add the removed object to a different Array for the different day. This part is suitable for an ArrayList but it has no size limit so I'm stuck with what the best solution is. Any ideas that I can look into?
Thanks

You can try the below, start from an array and convert it to list via Arrays.asList. Just note you could only use the set() method on the List, and not the add/remove methods as these would modify its size :
String[] array = {"a1","b2","c3"};
List<String> fixed = Arrays.asList(array);
fixed.set(0, "new_string"); // OK
fixed.add("aNewString"); // This will throw an exception

You can extend a class which already has the functionality you need and only override the methods required to implement new functionality (i.e. enforce a size limit).
Consider the following solution:
public class CappedList<T extends Object> extends ArrayList<T> {
private final int maxSize;
public CappedList(int maxSize) {
this.maxSize = maxSize;
}
#Override
public boolean add(T e) {
if (this.size() == this.maxSize) {
//Already reached max size, abort adding
throw new IllegalStateException("List is maxed out");
} else {
return super.add(e);
}
}
}
For completeness, you need to also override all add and addAll overloaded methods. You can then use this CappedList class instead of a simple ArrayList. A utility function isMaxedOut would be handy, in order to avoid exception handling:
public boolean isMaxedOut() {
return this.size() == this.maxSize;
}

It all depends how far you are in understanding of the language.
Let's say, first of all as a base logic that you might consider is, that you should find what is unique for 10 tickets. Obviously it's a group, which has own unique identifier and that's a date, so you have to concentrate on binding your tickets to a date groups, then you should control the amount what you are populating per date, you might need advanced control logic, rather than an usual variable that might do the job for you.
First of all, I would not store tickets in a different variables per day.
Let's go into details.
If you are obsessed by using only one specific property and that's ArrayList, I found nice answer here
But to have more precise population and access to the list later, for example to filter out specific date and see those tickets that are sold that day you should do it with a bit more structured logic, rather than a simple ArrayList(), may be you should even use different Type of variable that you should store that data in.
If you are on a bit advanced programming course, from the brief observation, for a simple task I might say that there is the way to use getter and setter methods to implement limitations and you could use any type of object to store that data, beside ArrayList.
Or you could write own functions that can control adding and removing elements from a list.
Or in more advanced way, if you have been introduced to a class concept, you could use class to define a ticket and then you could construct any logic behind it. This last one is the best way to go - to write easily readable, understandable and reusable code, or store specific data and control it the way you want.

Related

Java Hash Map Performance

protected static final Map<String, Integer> m = new HashMap();
I have a question in regards to performance of using the above. I am creating a 2D Tile Engine for a simple RPG game. I am using the hash map above to store the name of a tile along with its respected color code (Ex: 0xff00ff21). Since this is a game, the code m.get("name");is called an enormous amount of times to check if a tile is updated or not. (Ex: The render method with my computer runs at about 850 times per second). Please also note, I made sure to declare the HashMap outside of any loops and that it is initialized via a method call(also static) through the constructor that m.put("name", value) inputs all the information.
1) Is using a HashMap in this way a good idea? Is there perhaps another way to go about this more efficiently.
2) Is using a static final implementation of a hashMap good practice? The values will never change and the values used will be needed within the super class and its sub classes (Hence the "protected"). Can I set the key and value variables to final as well?
3) I understand that HashMap doesn't allow for duplicate keys, but from tinkering around with the HashMap, by inputting two of the same keys it simply replaces the older key and value with the newest .put("name", value);Is there to a way to throw an error perhaps if you try to .put("water", 0xff00ff21) and .put("water", 0xff221133) and/or .put("water",0xff00ff21)
Thank you for your time. New to this community and looking forward to helping/getting helped.
Please note that it is bad to ask three questions in one post.
1) IMO, yes. I usually use a HashMap for this kind of things. This can clarify things a lot better and enhance the readability of your code. Just imagine if you you only use hex color values for these kinda things, I think a lot of people would ask you what is 0xff221133 and what is 0xff00ff21.
2) Yes it is! static final is used when you want to declare some kind of constant. However, declaring a hash map as static final doesn't mean that its content cannot be changed. To prevent this, encapsulate the map in a class and only provide get methods:
final class TileColorMap {
private static final HashMap<String, Integer> tileColorMap = //blah blah blah
static {
//Add things to your map here
}
public static int get(String key) {
return tileColorMap.get(key);
}
}
3) If you look at the docs, specifically, Hashmap<>.put, you will see that:
Returns: the previous value associated with key, or null if there was no mapping for key. (A null return can also indicate that the map previously associated null with key.)
So you can add a method that put something into the map and will throw an exception if the key is a duplicate by checking whether the returned value is null.
private static void putStuffInMap (String key, int value) {
Integer returnedValue = tileColorMap.put(key, value);
if (returnedValue != null) {
throw new RuntimeException("Duplicate Keys!");
}
}
1) I'm not sure I understand what you're doing here, but how many different kinds of tiles could you be using here? You might be better off just defining a Tile object with a few constant Tiles that you can just reuse again and again by referring to Tile.WATER, etc instead of doing a hashtable lookup. If water has multiple colors just put them all in the water Tile object and pick from amongst them.
public class Tile
{
public static final Tile WATER = new Tile(...);
public static final Tile ROCK = new Tile(...);
}
2) Making a hashmap instance static and final doesn't make it immutable. The contents can still be updated. There's no performance benefit anyway. A read only hashmap wouldn't be any faster than a writable one. If you don't want it updated, just don't update it. It's your code, it's not like it's going to write to the hashmap when you aren't looking.
3) You could subclass hashmap and make it not accept duplicate keys, but again, I'm not sure what the purpose of this is- why aren't you sure what colors your tiles will be at run time? This strikes me as the kind of thing decided before compile time.
Using HashMap should be efficient enough. Is there more efficient way? Of course there will always be but whether it is appropriate depends on your design. For example, if tiles are statically defined, you may use enum/integer constants to represent a tile (instead of using "name"), and your tile-to-XXX mapping can be easily expressed as ArrayList or even array. (Again, it may not be appropriate to your design).
Again it depends on the design. Are the class containing the map something that is going to instantiate multiple times but you really want each instance to share same mapping? Are you going to give flexibility to the child class to set up the mapping? It is only meaningful to make it static if first answer is YES and second is NO.
To avoid change of content for the map, you can wrap it in a unmodifiable map:
// Access your data through this, so you won't mistakenly modify it
protected final Map<...> tileColorMap = Collections.unmodifiableMap(getTileColorMap());
// your super class or sub-class is providing the actual map
protected Map<...> getTileColorMap() {
Map<...> tileColorMap = new HashMap<>();
// do your setup
return tileColorMap;
}
If you are using Java 8+, it may be better to use Map#merge() method, and have the remapping function throw an exception you desire. Compared with the approach given by other answers, using merge() is safer as original value won't be mistakenly replaced. You may also selectively throw the exception if the new value is different from existing value.

Is it a bad practice to add elements to List using getter method in java?

Suppose I have a private ArrayList or a LinkedList inside a class, that I will never assign new reference to it, or in other words this will never happen:
myLinkedList = anotherLinkedList;
So that I won't need to use setMyLinkedList(anotherLinkedList).
But! I need to add elements to it, or remove elements from it.
Should I write a new kind of setter to only, do the task of adding instead of setting, like myLinkedList.add(someElement)?
Or it is OK to do this by using getter, without disobeying Encapsulation principal?
getMyLinkedList().add(someElement)
( + Suppose I am going to lose my mark if I disobey encapsulation :-")
I don't think it a particularly great practice to do something like:
myObj.getMyList().add(x);
since you are exposing a private class variable in a non read only way, but that being said I do see it pretty frequently(I'm looking at you, auto generated classes). I would argue that instead of doing it that way, return an unmodifiable list and allow users of the class to add to the list via an explicit method:
public class MyClass{
private final List<String> myList = new ArrayList<String>();
public List<String> getList(){
return Collections.unmodifiableList(this.myList);
}
public void addToList(final String s){
this.myList.add(s);
}
}
EDIT After reviewing your comments, I wanted to add a bit about your setter idea:
I meant using that line of code inside a new kind of setter inside the class itself, like public void setter(someElement){this.myLinkedList.add(someElement);}
If I'm understanding you correctly, you are saying you want to expose a method that only adds to your list. Overall this is what I think you should be shooting for, and what many have outlined in the answers, however, labeling it as a setter is a bit misleading since you are not reassigning (setting) anything. That, and I strongly recommend returning a read only list from your getter method if possible.
I would suggest in this case it would be best to follow your Encapsulation principals and use a method for adding elements to the list. You have restricted access to your list by making it private so that other classes cannot directly access the datatype.
Let the class that stores your ArrayList have direct access to the list, but when other classes want to add to the list, use an add() method.
In general, you should not assume that the list being returned by the getter is the original one. It could be decorated or proxied for example.
If you want to prevent that a new list is set on the target object, you could define an add method on the target class instead.
As soon as you have a Collection of any kind, it is generally not a bad idea to add methods like add(), remove() to the interface of your class if it makes sense that clients can add or remove objects from your private list.
The reason why it is useful to have these extra methods implemented (it might seem like overkill, because after all those methods mostly just call the method on the Collection) is that you protect evil clients from doing things to your list you don't want them to do, because the interface of most Collections contain more than just the add() and remove() methods and mostly, you don't want clients to be messing around with things you can't control. Therefore the encapsulation principle is that important to your teacher.
Another plus: if at any time, you would decide that a certain condition must be met when an object is added to your list, this can easily be implemented in the method you already have. If you give a client access to the direct reference of your list, it is not easy at all to implement this kind of things (which are not rare).
Hope this helps
So you have a class containing a List field (it should be final, since you don't intend to assign to it), and you want to allow callers to add to the List, but not be able to replace it.
You could either provide a getter for the list:
public List<E> getMyList() {
return myList;
}
Or provide a method to add to that list:
public void addToMyList(E e) {
myList.add(e);
}
Both are valid design decisions, but which you use will depend on your use case. The first option gives callers direct access to the List, effectively making it public. This is useful when users will be modifying and working with the list repeatedly, but can be problematic as you can no longer trust the List is in any sort of reliable state (the caller could empty it, or reorder it, or even maliciously insert objects of a different type). So the first option should only be used when you intend to trust the caller.
The second option gives the caller less power, because they can only add one element at a time. If you want to provide additional features (insertion, add-all, etc.) you'll have to wrap each operation in turn. But it gives you more confidence, since you can be certain the List is only being modified in ways you approve of. This latter option also hides (encapsulates) the implementation detail that you're using a List at all, so if encapsulation is important for your use case, you want to go this way to avoid exposing your internal data structures, and only expose the behavior you want to grant to callers.
It depends on the application - both are acceptable. Take a good look at the class you're writing and decide if you want to allow users to directly access the contents of the list, or if you would prefer that they go through some intermediate process first.
For example, say you have a class ListEncrypter which holds your MyLinkedList list. The purpose of this class is to encrypt anything that is stored in MyLinkedList. In this case, you'd want to provide a custom add method in order to process the added item before placing it in the list, and if you want to access the element, you'd also process it:
public void add(Object element)
{
MyLinkedList.add(encrypt(element););
}
public Object get(int index)
{
return decrypt(MyLinkedList.get(index););
}
In this case, you clearly want to deny the user's access to the MyLinkedList variable, since the contents will be encrypted and they won't be able to do anything with it.
On the other hand, if you're not really doing any processing of the data (and you're sure you won't ever need to in the future), you can skip creating the specialized methods and just allow the user to directly access the list via the get method.

Storing 15,000 items in Java

I have a document with 15,000 items. Each item contains 6 variables (strings and integers). I have to copy all of these into some sort of two dimensional array, what the best way to do it?
Here are my ideas so far:
Make a GIANT 2D array or array list the same way you make any other array.
Pros: Simple Cons: Messy(would create a class just for this), huge amount of code, if I make a mistake it will be imposable to find where it is, all variables would have to be string even the ints which will make my job harder down the road
Make a new class with a super that takes in all the variables I need.
Create each item as a new instance of this class.
Add all of the instances to a 2D array or array list.
Pros: Simple, less messy, easier to find a mistake, not all the variables need to be strings which makes it much easier later when I don't have to convert string to int, a little less typing for me Cons: Slower? Will instances make my array compile slower? And will they make the over all array slow when I'm searching to items in it?
These ideas don't seem all to great :( and before I start the three week, five hour a day process of adding these items I would like to find the best way so I won't have to do it again... Suggestions on my current ideas or any new ideas?
Data example:
0: 100, west, sports, 10.89, MA, united
*not actual data
Your second options seems to be good. You can create a class containing all the items and create an array of that class.
You may use the following:
1. Read the document using buffered reader, so that memory issues will not occur.
2. Create a class containing your items.
3. Create a List of type you need and store the elements into it.
Let me know in case you face further problems.
If you already have the document with the 15000 * 6 items, in my experience you would be better served writing a program to use regex and parse it and have the output be the contents of the java array in the format you want. With such a parsing program in place, it will then also be very easy for you to change the format of the 15000 lines if you want to generate it differently.
As to the final format, I would have an ArrayList of your bean. By you text thus far, you don't necessarily need a super that takes in the variables, unless you need to have subtypes that are differentiated.
You'll probably run out of static space in a single class. So what I do is break up a big class like that into a file with a bunch of inner nested classes that each have a 64K (or less) part of the data as static final arrays, and then I merge them together in the main class in that file.
I have this in a class of many names to fix:
class FixName{
static String[][] testStrings;
static int add(String[][] aTestStrings, int lastIndex){
for(int i=0; i<aTestStrings.length; ++i) {
testStrings[++lastIndex]=aTestStrings[i];
}
return lastIndex;
}
static {
testStrings = new String[
FixName1.testStrings.length
+FixName2.testStrings.length
+FixName3.testStrings.length
+FixName4.testStrings.length
/**/ ][];
int lastIndex=-1;
lastIndex=add(FixName1.testStrings,lastIndex);
lastIndex=add(FixName2.testStrings,lastIndex);
lastIndex=add(FixName3.testStrings,lastIndex);
lastIndex=add(FixName4.testStrings,lastIndex);
/**/ }
}
class FixName1 {
static String[][] testStrings = {
{"key1","name1","other1"},
{"key2","name2","other2"},
//...
{"keyN","nameN","otherN"}
};
}
Create a wrapper (Item) if you have not already(as your question does not state it clearly).
If the size of the elements is fixed ie 1500 use array other wise use LinkedList(write your own linked list or use Collection).
If there are others operations that you need to support on this collection of items, may be further inserts, search( in particular) use balanced binary search tree.
With the understanding of the question i would say linked list is better option.
If the items have a unique property (name or id or row number or any other unique identifier) I recommend using a HashMap with a wrapper around the item. If you are going to do any kind of lookup on your data (find item with id x and do operation y) this is the fastest option and is also very clean, it just requires a wrapper and you can use a datastructure that is already implemented.
If you are not doing any lookups and need to process the items en masse in no specific order I would recommend an ArrayList, it is very optimized as it is the most commonly used collection in java. You would still need the wrapper to keep things clean and a list is far cleaner than an array at almost no extra cost.
Little point in making your own collection as your needs are not extremely specific, just use one that is already implemented and never worry about your code breaking, if it does it is oracles fault ;)

Choose a class depending on the class' attribute

I want to write a method in java that will select certain words based on an input.
For example, if the choices were a dog, cat, lizard, eagle
and someone types in wings, it'll check to see if the choices have that attribute.
I don't know how complex this is but we've learned for loops, return, if, else and scanners so far.
You can probably maintain a list of attributes for each object, then check if the user typed attribute is part of the list for all object types you have in hand.
I suggest you look at the ArrayList JavaDoc, you will need to use it to maintain the list of attributes. If you don't feel at ease with using an ArrayList object to hold onto your attributes, you may want to use a String array instead, which will work fine too. You will also need to defined a class hierarchy and define a method that will be available in all subclasses (here's a tutorial on inheritance).
Edit
I posted this first answer before reading the comments.
If your only assignment is to provide a list of components that freeze at the user specified temperature, then a list of attributes isn't necessary. You can define a super class (lets say Element) that will define an abstract method public int getFreezingTemperature (). Then, in all subclasses, you will have to implement this method. As an example, if you create a class Water:
public class Water extends Element {
#Override
public int getFreezingTemperature () {
return 0;
}
}
And repeat the same for every element you have to create. Once you are done, whenever a user inputs a temperature, you can query your elements via the method getFreezingTemperature (), and whenever the returned temperature is above the user specified temperature, add it to a list of elements that freeze at the specified temperature.
I'm attempting to answer the substance-temperature question you mentioned in your comment. You could make an arrays as such:
String[] substances = new String[number of substances given];
Then place the substances into the array in the same order that they are given in the assignment. You can then check the user's input and determine at which index the name of the substance corresponding with their input is. For example:
//code to initialize array of substances goes here, call it "substArray"
//code to make scanner goes here, call it "scan"
int temp = scan.nextInt();
if(temp == -100)
{
System.out.println(substArray[index of substance corresponding with -100]);
}
else if...
...
This seems to be a very messy and a not very elegant program to write without use of separate classes, but hopefully this is within the range of your current knowledge and understanding.
I hope this helps,
Tyler
Edit: after reading your comments, it looks like you're going to want to do something like this.
//create your scanner, using whatever resource you are told to use
int temp=scanner.readInt()
//read in the given temperatures
if(substance1freezingpoint > temp){
System.out.println("substances 1 will freeze at " + temp);
}
if(substance2freezingpoint > temp){
System.out.println("substance 2 will freeze at " + temp);
}
....
A couple of things to note about that implementation.
It assumes that more than one substance can freeze at temp. If that isn't the case, you're going to want to use else ifs. As a question to test your learning: why is that?
It doesn't store which substances will freeze at a certain temperature, it just prints them out to the screen. How would you modify this to store the substances which meet the criteria
It doesn't deal with boiling points, but it's a pretty easy modification to make it do that.
So, does that code at least get you off on the right foot, or does it not satisfy what the problem is asking?

Vectors in Java, how to return multiple vectors in an object

I'm working on a java program, and I have several vectors defined and filled (from a file) inside a method. I need to return the contents of all the vectors from the method. I have heard you can put them all in one object to return them. Is that possible, and if so, how? If not, do you have any possible solutions for me? Thanks in advance for your help!
Here is a code snippet:
Object getInventory()
{
Vector<String> itemID=new Vector<String>();
Vector<String> itemName=new Vector<String>();
Vector<Integer> pOrdered=new Vector<Integer>();
Vector<Integer> pInStore=new Vector<Integer>();
Vector<Integer> pSold=new Vector<Integer>();
Vector<Double> manufPrice=new Vector<Double>();
Vector<Double> sellingPrice=new Vector<Double>();
Object inventoryItem=new Object(); //object to store vectors in
try
{
Scanner infile= new Scanner(new FileReader("Ch10Ex16Data.txt"));
int i=0;
while (infile.hasNext())
{
itemID.addElement(infile.next());
itemName.addElement(infile.next()+infile.nextLine());
pOrdered.addElement(infile.nextInt());
pInStore.addElement(pOrdered.elementAt(i));
pSold.addElement(0);
manufPrice.addElement(infile.nextDouble());
sellingPrice.addElement(infile.nextDouble());
i++;
}
infile.close();
System.out.println(itemID);
System.out.println(itemName);
System.out.println(pOrdered);
System.out.println(pInStore);
System.out.println(pSold);
System.out.println(manufPrice);
System.out.println(sellingPrice);
}
catch (Exception f)
{
System.out.print(f);
}
return inventoryItem;
}
Personnally, I'd scrap that approach completely. It seems like you need a Product class:
public class Product {
private String itemName;
private int itemID;
// etc etc
public Product(String itemName, int itemID) {
this.itemName = itemName;
this.itemID = itemID;
// etc etc
}
public String getItemName() {
return itemName;
}
public int getItemID() {
return itemID;
}
// etc etc
}
Then something like this :
public class Invertory {
private List<Product> products = new ArrayList<Product>
// etc etc
public Inventory(String fileName) throws IOException {
// Load file,
// Read each product,
products.add(new Product(...product arguments); //add to array
}
public Product[] getProducts() {
return products.toArray(new Product[]{});
}
}
First of all, use ArrayList instead of Vector. Then use a Map as your return object, with each value of the entry is one of your Lists.
Second of all, a much better approach is to create an object that actually holds each of your fields and return a java.util.List of these objects.
public class Item
{
String id;
String name
Integer pOrdered;
Integer inStore;
:
:
You're doing a few things wrong.
Firstly, don't use Vector. Like, ever. If ordering is important to you, you want List on the API (and possibly ArrayList or LinkedList as an implementation).
Secondly, you're trying to have a large number of arrays have values that happen to line up. That's going to be nearly impossible to use. Just create a class that represents one record, and return the List of those.
Thirdly: do not catch that exception. You don't know what to do with it, and you're just going to confuse yourself. Only catch an exception if you have a really good idea what to do in the error case (printing out an error message without a stack is just about never the right thing).
The signature of your method is the most important part. If you get that right, the implementation doesn't matter nearly as much. Aim for something that looks like this:
List<Item> getInventory(File input) throws IOException {
}
You really should reconsider your design here. You have multiple vectors, each with properties of the same type of thing — an item in your inventory. You should probably turn this into a single class, perhaps InventoryItem, with members for the name, price, etc. Then, when reading in each item, you construct an InventoryItem with the given properties, and return a single Vector<InventoryItem>.
If you're really attached to keeping track of all those individual Vectors, you could just return a Vector[] with all the vectors you have:
return new Vector[] { itemID, itemName, pOrdered, pInStore, pSold, manufPrice, sellingPrice };
Also, as Robin says, you should use the ArrayList container instead of Vector. The only thing that will change is that you need to change all calls to someVector.AddElement to someList.add.
Sounds like this should be tagged "Homework".
Okay, first of all, are you required to use all these Vectors, or is that your own decision? Though some may point out that using ArrayLists is better, I'd do away with them and create your own Item class.
This way, instead of having a conceptual item's properties distributed across multiple Vectors (the way you're doing now) you have 1 Item instance per item, with fields for all the data relevant to that item. Now, you only need one data structure (Vector or ArrayList) for all your item objects, and you can return that structure from getInventory().
The easiest way to declare the object would be something like
List<Vector<? extends Object>> inventoryItem = new ArrayList<Vector<? extends Object>>
but this has several problems, namely that Java's generics aren't reified, so you have to test and cast the contents of each vector that you get back. A better solution would be to define a container object that has each of the Vectors as fields and add to those.
However, this looks like it is really missing the point. Instead, you should define an InventoryItem who has each of your seven fields. Each time you read an object from the file, instantiate a new InventoryItem and populate its fields. Then, you add this to a single Vector.
Also, it is generally recommended that you do not use the Vector class. Instead, you should use ArrayList. Vector should really only be used if you need its synchronization properties, and even then you should consider wrapping some other list in a Collections.synchronizedList().
Finally, the places where you would want to catch just an Exception can be counted on one hand. You should really be catching an IOException and even that you might want to consider just rethrowing. Also, you should call printStackTrace() on the exception rather than System.out.println().
I find that a good rule of thumb is that it's never really a good idea to pass collections around outside your objects. They are obviously useful inside your object, but outside you lose control and they are not obvious.
Consider the principle of making your code readable instead of documenting it. If you take a collection, how does that tell the caller what to pass in? Even if you use generics, there is no way to assert control over what happens to the collection--someone could be adding to it and deleting from it in another thread after it's passed to you.
There is no reason not to create a business class that contains your collections along with the business logic to manipulate them (yeah, there is always business logic--it's the copy and paste code you'll find around the locations that you access the collection).
I used to find it frustrating that the JDK always seems to take arrays of built-in types rather than collections, but it makes a lot more sense after coming to terms with the idea that passing collections (like passing around any basic type) is just not a very good idea.
While in general I heartily agree with the advice to use List/ArrayList instead of Vector, it is important to know why. Indeed, I have to vehemently disagree with Dustin who says not to use Vector "ever".
A Vector is in essence a synchronized ArrayList. If you truly need synchronization, by all means then, ignore Dustin's admonition, and use Vector.
There is another instance in which Vector is justified. And that is when you need to maintain compatibility with a pre-Java2 code base.

Categories