## What’s a bag?

• Ignore computers for a minute (actually, ignore them forever, they are foul machines): describe a bag.
• What can you put in a bag?
• What order, if any, is there in a bag?
• Can we have duplicates of the same item?
• Given a bag big enough, how much can you fit in it?
• A Bag ADT will therefore:
• Allow any number of items (within limits of memory and reasonability)
• Allow duplicate items
• Allow any type of items (or allow restricting the types, since that’s also useful).

## The methods of Bag

• Again, let’s think about a real bag. What can you do with a bag and its items?
• You can put something in it
• You can take something out of it (any random thing, or a specific thing)
• You can take everything out of it and throw them away
• You can count the items in it, or ask if it’s empty
• You can ask if a particular item is in it
• You can get a listing of the items
• You can get a count of how many of one kind of item there are
• Let’s classify these…
• Some of these actions change the bag, while others just ask questions about it.
• When an action changes something, we say it mutates it.
• When you cannot change something, we say it is immutable. That’ll come up again.
• Of the ones that change it, some add things and some remove things.
• Some of them are redundant.
• For example, “is the bag empty?”
• How else could you implement that?
• By seeing if there are 0 items in it.
• So why do we add it?
• Well, this is up to you.
• You might add it because it’s a common, useful operation.
• Ultimately, it’s a judgment call.
• So let’s list them out.
• (see BagInterface.java)

## Default methods

• Java 1.8 and newer actually do have a way to provide default implementations of interface methods
• They’re called default methods and yes, you write them in the interface
• The default methods can only call other methods in the same interface
• This can greatly reduce the amount of code needed to implement an interface
• As an example, the isEmpty() method of BagInterface
• All it needs to know is if the size is 0
• Now, when a class implements BagInterface, it gets this method “for free”
• The class can still override it, like usual
• But hey, avoiding copying and pasting is great!

• The comments can then be extracted and transformed into e.g. a webpage
• All the Java API documentation is produced using these!
• Java uses a system called Javadoc
• They look like regular block comments, but start with a slash and two stars: /** ... */
• The text inside just becomes the description of the method/class
• In addition, there are many commands for adding more detailed docs
• Common commands for methods are:
• @param <name> <documentation> - details the meaning of the parameter named <name>
• @return <documentation> - details the meaning of the return value
• @throws <ExceptionName> <documentation> - if your method intentionally throws an exception, details under what circumstances they are thrown
• You’ll be learning and using Javadoc, as it’s widely used in industry and open source
• If you explain something to someone else, you will get a better understanding of it yourself.
• As a corollary…
• If you have great difficulty explaining something, it’s probably not well-designed.

## Things the language enforces vs. “contracts”

• Java can only enforce some things
• Parameter types
• Return types
• What exceptions may be thrown
• Java can’t enforce many important aspects of ADTs
• What data the ADT needs to store
• Not how the data is stored; this is abstract after all
• What the methods actually do to that data
• What special cases there are, and how to respond to them
• Special cases? Things like…
• What happens if you pass null as a parameter?
• Does the ADT have an “invalid” state?
• If it does, how do the methods behave when it’s “invalid?”
• If something “goes wrong”, do we signal it through an exception, or through a return value?
• These can’t be enforced by the language
• But we should still document them
• This way the implementors and users will know what to expect

## Implementing the BagInterface

• If you want to hold several items…
• What do you know about that can do that?
• Arrays.
• Pros and cons of arrays
• You can store many items, as many as you need
• You can declare the array as the parameterized type, to keep the array homogeneous
• Arrays can’t be resized
• If you have fewer items than array slots (the typical case), you have to keep track of how many items you have, separately
• We call the size of the array the capacity - how many items could be stored in the array if it were full
• The easy way out: fixed-size arrays
• Create the array once, when the Bag is created - fixed capacity
• Then just fail if the user tries to add more than that many items
• E.g. capacity is 20, they try to put 21 in
• On the 21st item, we could either throw an exception or return a value to indicate something went wrong
• Depends on how we defined the interface and contract!
• This is easy to implement and predictable
• You know that it will just fail if you try to add too many
• But it’s inflexible and might waste space
• If you set the capacity to the “worst case” (e.g. 1000 items), but only use 10 most of the time… what a waste!
• See FixedArrayBag.java and Ex11FixedArrayBagDriver.java for an implementation.

## A more flexible implementation

• “Resizing” arrays
• Java will not allow you to change the length of an array
• But you can make a new array and copy the data from the old array into it
• E.g. the capacity is 20. The user adds 20 items. Everything is fine. But then they add a 21st.
• Create a new, bigger array
• Copy the 20 old items into it
• Insert the 21st item into it
• The user doesn’t have to know or care that this is happening in our bag implementation
• A changeable capacity
• Since the user will no longer specify the capacity, we, the implementors will
• What should the default capacity be?
• I mean, it could be anything
• Really - it doesn’t matter since we can always make it bigger if needed
• What should the maximum capacity be, if any?
• We might want to set a maximum capacity to avoid issues if the user goes into an infinite loop and adds items forever
• Should this be a constant? Should it be settable?
• When we need to “grow” the array, by how much should we do so?
• Growing too slowly will cause lots of resizes
• And resizes are slow
• Growing too quickly will waste space
• Common rule is to double the size
• Will we ever shrink the capacity?
• What if the user adds 1000 items, then removes them all?
• Should we keep 1000 slots around, or free up some memory by resizing smaller?
• Should this be configurable?
• So many options!
• How do we copy the array?
• java.util.Arrays.copyOf(E[] original, int newLength) to the rescue
• The old array can just… float away
• The garbage collector will sweep it up
• (See ArrayBag.java and Ex12ArrayBagDriver.java for a variable-capacity implementation)