Abstract Data Types (ADTs) An ADT consists of: –a set of values, and –a set of operations on those values. Example: rational numbers –some values: 15/7, -3/4, 123/1, 0/1 (but NOT 1/0 !) –some operations: addition, multiplication, negation An ADT therefore specifies: –what the members are, and –what operations are supported.
What an ADT isn’t: An ADT does not specify: –how the data is stored/represented, or –how the operations are implemented. These details are abstracted away. An ADT is implementation independent An ADT is language independent. In Java, an ADT is typically specified in an interface.
Data Structures (DS) A data structure is an implementation of an ADT. In Java, data structures are classes. In the Java Collections framework, the List interface specifies an ADT that is implemented by several data structures: –ArrayList (an array-based structure) –LinkedList (a linked structure)
Analogy #1: vending machine You can perform only the specific tasks that the machine's interface presents to you. You must understand these tasks. E.g. you must know what to do to buy a beverage. You cannot see or access the inside of the machine, because a steel shell encapsulates it. You can use the machine even though you don't know what happens inside. If someone replaced the machine's inner mechanism with an improved version, leaving the interface unchanged, you could still use the machine the same way.
Analogy #2: car Basic interface is the same: –steering wheel to determine path –gearshift (on an automatic) to determine direction (drive/reverse) –pedals to determine speed (accelerator/brake) Underlying implementation is irrelevant –steering: recirculating ball, rack & pinion –transmission: 3, 4 or 5 speed, CVT –engine: 4, 5, 6 or 8 cylinder, gas, diesel, CNG or hybrid Client treats them all the same!
What if the interface changes? How easy is it for people to switch from driving an automatic to a manual transmission car? Automatic: –gear selector: drive/reverse –pedals: accelerator, brake Manual: –gear selector: 1, 2, 3, 4, 5, R –pedals: accelerator, brake, clutch Client needs to adjust to the new interface!
With an ADT The client can only perform the operations specific to the ADT. The client must adhere to the specifications of the operations that the ADT provides. Thus, client must understand how to use the operations.
Interacting with a List (ADT) The client cannot access the data within the list without using an ADT operation. The principle of encapsulation hides the data within the ADT. The client can use the ADT, even though it can't access the data directly, and does not know how it is stored. If you vary the implementation, but maintain the interface, the client isn’t affected and doesn’t have to care.
Examples of ADTs Bag – unordered collection, allowing duplicates Set – unordered collection, no duplicates List – ordered collection – client determines order Sorted list – comparator determines ordering Stack – Last-In First-Out (insert/remove from front) Queue – First-In First-Out (insert back, remove front) Tree – hierarchical organization Binary Search Tree – comparator determines ordering –a simple BST makes no performance guarantees –more advanced BSTs can make performance guarantees Dictionary – collection of key-value pairs Graph – collection of vertices and arcs
Creating an ADT To define an ADT, we Describe its data Specify the operations on that data Focus on “what”, not “how”.
Bag ADT Values: object references (unordered). We use generics to define a parameterized type. The type of the members of the ADT is specified by a type parameter in the definition of the interface.
Bag Operations Basic operations: –add (client has no control over placement; returns a boolean, multiple references to same object are permitted) –remove (based on object identity, i.e. == on object references; returns a boolean) –contains (membership test, based on object identity; returns a boolean) –size (how many values are in a given bag)
Implementation options There are two basic approaches: –array-based –linked We will consider array-based implementation first Use a TDD approach: first consider what the essential functionality of a given ADT is.