06
-
6.0 Enum Types
- An Enum (enumeration) is a type defined to represent a fixed set of constant values, i.e. it is a complete order listing of a collection of a values of a type. The fields of the type represent the values and are specified in capitals as constant values; all the values must be specified at compilation time. Variables of an Enum type can only hold one of the constant values.
-
public enum Month{ JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER } Month firstMonth = Month.JANUARY; Month lastMonth = Month.DECEMBER; for (Month m : Month.values()) System.out.println(m);
- Note, "values()" method returns all values of an Enum type.
- Enum types are more powerful in Java than other languages where an Enum type is a class which can have methods and other fields, other methods are added by the compiler. The constructor for an Enum type must be package-private or private access. Enums automatically creates the constants that are defined at the beginning of the Enum body.
-
public enum CustomerType { INTERNAL_ACCOUNT (0.25, 2), EXTERNAL_ACCOUNT (0.1, 1), EXTERNAL_NOACCOUNT (0, 3); private final double discount; private final int priorityLevel; CustomerType(double discount, int priorityLevel) { this.discount = discount; this.priorityLevel = priorityLevel; } private double getDiscount() { return this.discount; } private int getPriorityLevel() { return this.priorityLevel; } } public class Customer { private int customerId; private String customerName; private String customerAddress; private String customerEmail; private CustomerType customerType; private static int numberOfCustomers=0; public Customer() { this.customerId = ++numberOfCustomers; this.customerName = null; … this.customerType = CustomerType.INTERNAL_ACCOUNT; } public Customer(String customerName, String customerAddress, String customerEmail, CustomerType customerType) { … this.customerType = customerType; } Customer c = new Customer( "Puyol", "Segur", "charlie@barca.com", CustomerType.EXTERNAL_ACCOUNT);
-
6.1 Collections
- A collection is an object that groups multiple elements – generally of the same class. They are used to store, retrieve and manipulate data which forms a group for the app’s purpose. Java defines a "Collections Framework" which provides an architecture for defining different types of collections and their manipulation. The framework consists of three parts:
- Interfaces
- Implementation
- Algorithms
- Collections have several benefits, they:
- Reduces programming effort
- Increases program speed and quality
- Allows interoperability among unrelated APIs
- Reduces effort to learn and to use new APIs
- Reduces effort to design new APIs
- Facilitates software reuse
- Interfaces are abstract data types that represent collections, they allow collections to be manipulated independently of the details of their representation and generally form a hierarchy. The core collection interfaces are the foundation of java collections and encapsulate six main types of collections; Set, List, Map, Queue, Deque, SortedSet, SortedMap. Note, a Map is not a true collection.
- All core collection interfaces are generic (public interface Collection
...) and the actual type a "Collection" class instance is to store should be specified at time of declaration. Concrete implementations need not specify all the operations defined in the interface, if an operation is invoked which is not specified then a "UnsupportedOperationException" is thrown. - Collection Interfaces are the root of collection hierarchy. They group of objects known as elements and are used to pass collections around and to manipulate them when maximum generality is desired. Collections have no direct implementation, implementations exist of more specific subinterfaces, e.g. ArrayList, HashSet etc. By convention all general-purpose collection implementations have a constructor that takes a Collection argument. This is known as a conversion constructor which initializes new a collection to contain all of elements in specified collection and allows you to convert the collection's type.
List<String> list = new ArrayList<String>(c); List<String> list = new ArrayList<>(c); (> JDK 7)
- Basic Methods: size(), isEmpty(), contains(), add(), remove(), Iterator<E> iterator()
- Collection Methods: containsAll(), addAll(), removeAll(), retainAll(), clear()
- Other Methods: toArray()
- Stream Methods: (JDK 8)
- stream(), parallelStream()
- From JDK 8 in order to traverse collections we use aggregate operations which obtain a stream and perform aggregate operations on it. These are often used in conjunction with lambda expressions to make programming more expressive (use less lines of code). Unlike lists collections have no set order, you have add to collections, remove from collection, iterate over collections and query the size of a collection, but you cannot reference a specific element of a collection because they are not defined.
for (Object o : collection) System.out.println(o);
Interfaces
-
6.2 Iterators
- An Iterator is an object that enables you to traverse through a collection and to remove elements from the collection selectively, if desired. A collection has an iterator() method which returns an Iterator object.
public interface Iterator<E> { boolean hasNext(); E next(); void remove(); //optional
- The "remove()" method removes last element returned by "next()" and is the only safe way to modify a collection during iteration. Use Iterator instead of for construct when you need to remove the current element or iterate over multiple collections in parallel. We can use an Iterator to filter an arbitrary Collection, i.e. traverse collection removing specific elements. Note, code is polymorphic i.e. works for any Collection regardless of implementation.
static void filter(Collection> c) { for (Iterator> it = c.iterator(); it.hasNext();) //iterate while we have next element if (!cond(it.next())) it.remove(); //if element does not match condition remove it }
-
6.3 Set Interface
- A Set object cannot contain duplicate elements, and two Set instances are equal if they contain the same elements. Sets have three general-purpose implementations:
- HashSet
- stores elements in a hash table
- best-performing implementation
- no guarantees concerning the order of iteration
- TreeSet
- stores elements in a red-black tree
- orders elements based on their values
- substantially slower than HashSet
- LinkedHashSet
- implemented as a hash table with a linked list running through it
- orders elements based on order in which were inserted
- spares clients from unspecified, generally chaotic ordering provided by HashSet at a cost that is only slightly higher
-
6.4 List Interface
- A list is an ordered collection (sequence) which may allow duplicate elements.
- Adds other operations:
- Access
- based on numerical position
- get(), set(), add(), addAll(), remove()
- Search
- returns numerical position
- indexOf(), lastIndexOf()
- Iteration
- listIterator()
- Range-view
- sublist() method performs arbitrary range operations on the list
- List have two general-purpose implementations:
- ArrayList
- usually better-performing implementation
- LinkedList
- offers better performance under certain circumstances
- An array class has a static factory method "asList()" which allows an array to be viewed as a List. A List's iterator() method returns an Iterator object which returns list elements in proper sequence a ListIterator is richer as it allows traversal in either direction, can modify list during iteration, and can obtain the current position of the iterator. Methods: hasNext(), next(), hasPrevious(), previous(), remove()
-
for( ListIterator<Type> it = list.listIterator(list.size()); it.hasPrevious(); ) { Type t = it.previous(); ... }
- List "add" allows to insert a new element into list immediately before current cursor position:
-
public static <E> void replace (List<E> list, E val, List<? extends E> newVals) { for (ListIterator<E> it = list.listIterator(); it.hasNext(); ){ if (val == null ? it.next() == null : val.equals(it.next())) { it.remove(); for (E e : newVals) it.add(e); } } }
- Most polymorphic algorithms in the Collections class apply specifically to List; sort, shuffle, reverse, rotate, swap, replaceAll, fillcopy, binarySearch.
-
6.5 Queue, Deque, and Map Interfaces, and Object Ordering.
- A queue interface is a collection for holding elements prior to processing. Typically, but not necessarily, they are used to order elements in a FIFO (first-in-first-out) manner; exceptions to this include priority queues, which order elements according to their values. Queues specifies additional insertion, removal, and inspection operations
- Deque "double-ended-queue" interfaces (pronounced as deck) support insertion and removal of elements at both end points. Methods are use to access elements at both ends of the Deque instance and allow us to insert, remove, and examine the elements. ArrayDeque and LinkedList implement the Deque interface. The Deque interface can be used both as last-in-first-out stacks and first-in-first-out queues.
- Map interfaces are objects that map keys to values. Maps cannot contain duplicate keys: each key can map to at most one value. There are three general-purpose Map implementations: HashMap, TreeMap and LinkedHashMap (analogous to HashSet, TreeSet, and LinkedHashSet). We can sort collections
- We can sort collections in a variety of different natural orders, a List l may be sorted using "Collections.sort(1)". For example, String and Date both implement Comparable interfaces, String can be sorted in alphabetical order (‘ASCII’ value) and Dates in chronological order; ClassCastException thrown if elements of list do not support Comparable.
-
6.6 Summary Of Interfaces & General-Purpose Implementations.
- Core collection interfaces are the foundation of the Java Collections Framework
- The hierarchy consists of two distinct interface trees:
- Collection interface
- basic functionality used by all collections e.g. add, remove
- sub-interfaces — Set, List, and Queue
- Map interface
- maps keys and values similar to a hashtable
- Collections can be manipulated independently of the details of their representation
- Set interface
- no duplicate elements
- subinterface - SortedSet
- List interface
- ordered collection - control over where each element is inserted
- can retrieve elements from a list by position
- Queue:
- elements typically ordered on a FIFO basis
- Deque:
- enables insertion, deletion, and inspection operations at both the ends
- can be used in both LIFO and FIFO
- Concrete implementations (you can call the methods of abstract class by overriding the methods of abstract class) of the collection interfaces
- Reusable data structures
- Different types of implementation
- general-purpose implementations are most commonly used
- one implementation of an interface is often the most suitable one to use
- HashSet, ArrayList and HashMap
- Each general-purpose implementations provides all optional operations contained in its interface
- All permit null elements, keys, and values
- None are synchronized (thread-safe)
- All have fail-fast iterators, which detect illegal concurrent modification during iteration and Fail quickly and cleanly rather than risking arbitrary, nondeterministic behavior at an undetermined time in the future
- All are "Serializable" and all support a public "clone()" method
- General-Purpose Set Implementations
- "HashSet" is much faster than "TreeSet" but offers no ordering guarantees
- use "TreeSet":
- if you need to use the operations in "SortedSet" interface
- if value-ordered iteration is required
- "LinkedHashSet" is in some sense intermediate between "HashSet" and "TreeSet"
- General-Purpose List Implementations
- "ArrayList" is most popular and fast
- Use "LinkedList":
- if you frequently add elements to the beginning of the "List"
- iterate over "List" to delete elements
- big cost in performance
- General-Purpose Map Implementations
- Use "TreeMap":
- if you need "SortedMap" operations or key-ordered "Collection"-view iteration
- Use "HashMap":
- if you want maximum speed and don't care about iteration order
- Use "LinkedHashMap":
- if you want near "HashMap" performance and insertion-order iteration
Interfaces Hash table Implementations Resizable array Implementations Tree Implementations Linked list Implementations Hash table + Linked list Implementations Set HashSet TreeSet LinkedMashSet List ArrayList LinkedList Queue Deque ArrayDeque LinkedList Map HashMap TreeMap LinkedHashMap -
6.7 Algorithms
- Algorithms are methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. Algorithms are polymorphic, i.e., the same method can be used on many different implementations of the appropriate collection interface (reusable functionality). They take the form of static methods whose first argument is the collection on which the operation is to be performed. The great majority provided by Java platform operate on List instances, but a few of them operate on arbitrary Collection instances:
- Sorting:
- reorders a "List" so its elements are in ascending order according to an ordering relationship
- two forms of the operation are provided:
- simple form takes a "List" and sorts it according to its elements' natural ordering
- second form takes a "Comparator"
- Shuffling:
- opposite of what sort does, destroying any trace of order that may have been present in a "List"
- Routine data manipulation on "List" objects:
- reverse, fill, copy, swap, addAll
- Searching:
- binarySearch searches for a specified element in a sorted List
- two forms:
- assumes List is sorted in ascending order according to natural ordering
- second form requires a Comparator and assumes that the List is sorted into ascending order according to the specified Comparator
- Composition (is-a, has-a):
- frequency (how many times it is-a/has-a), disjoint (do two collections contain these elements in common)
- Retrieve maximums and minimums.
-
6.8 HashSet Example
- We can add elements to the "HashSet" using the "add()" method:
-
Set<String> names = new HashSet<>(); names.add("Iniesta"); names.add("Messi"); names.add("Busquets"); names.add("Puyol"); names.add("Pique"); names.add("Puyol");
- toString
- The "Enum" type implements the "toString()" method:
-
System.out.println(names);
- for-each
- We can use the new version of the for-each construct to traverse the collection:
-
Iterator it = names.iterator(); while (it.hasNext()) System.out.println(it.next());
- iterator
- The "Collection" class defines an "iterator()" method which returns an "Iterator" object that can be used to traverse the collection:
-
Iterator it = names.iterator(); while (it.hasNext()) System.out.println(it.next());
-
if (names.contains(toBeRemovedElement)) { boolean result = names.remove(toBeRemovedElement); if (result) System.out.println("removed"); else System.out.println("not present"); } else System.out.println("not present");
- Recall from earlier that the "TreeSet" class is a concrete implementation of the "SortedSet" interface where elements are stored in their natural sorted order. We can change the definition of the names variable to a "TreeSet", note no other code requires changing:
-
Set<String> names = new TreeSet<>();
-
toString ======== [Busquets, Iniesta, Messi, Pique, Puyol] for each ======== name: Busquets name: Iniesta name: Messi name: Pique name: Puyol iterator ======== Busquets Iniesta Messi Pique Puyol
- Now let's create a "HashSet" of objects:
-
Set<Customer> customers = new HashSet<>();
- An add operation simply involves creating a new "Customer" object and invoking the "add()" method on the "customers" object:
-
customers.add( new Customer("Iniesta", "Fuentealbilla","andy@barca.com",CustomerType.INTERNAL_ACCOUNT) );
-
toString ======== [customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT, customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT, customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT, customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT, customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT, customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT ] for each ======== customer: customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer: customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer: customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer: customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer: customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer: customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT iterator ======== customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- Note this time “Puyol” can be added twice as the constructor for the Customer class allocates a new value for the customerId (remember hashsets do not allow identical elements) therefore the two "Customer" objects are distinct. Ids and their allocation need careful thought when you’re developing business systems.
- What about removal? Well again we can use the "contains()" method to determine if an object is contained in the collection and then "remove()" to remove it.
-
Customer toBeRemovedElement = new Customer("Puyol", "La Pobla de Segur","charlie@barca.com",CustomerType.EXTERNAL_ACCOUNT); if (customerSet.contains(toBeRemovedElement)) { boolean result = customerSet.remove(toBeRemovedElement);
-
Remove Element -------------- Element to be removed: customer id: 7, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT not present customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- If the removal fails, perhaps due to the fact that the element to be removed has "customerId" 7 while the element to be removed has" customerId" has 4 (or 6) let’s use the setter method for "customerId" to change the value of this field for the "toBeRemoved" object:
-
tobeRemoved.setCustomerId(4);
-
Remove Element -------------- Element to be removed: customer id: 7, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Element to be removed: customer id: 4, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT not present customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- The remove operation still fails as though the two objects contain the same values for fields they are different objects. Recall that all classes in Java ultimately derive from the Object class which defines an equals() method:
- 🔗 Java Class Object
- We can override this method in the "Customer" class to change the way in which "Customer" objects are tested for equality:
-
@Override public boolean equals(Object o) { if (o instanceof Customer) { Customer c = (Customer)o; return c.getCustomerId() == getCustomerId() && c.getCustomerName() == getCustomerName() && c.getCustomerAddress().equals(getCustomerAddress()) && c.getCustomerEmail().equals(getCustomerEmail()); } else { return false; } }
- We also require a hashCode() override, 31 is an arbitrary number:
-
@Override public int hashCode() { return getCustomerId() * 31 + getCustomerName().hashCode() * 31 + getCustomerAddress().hashCode() * 31 + getCustomerEmail().hashCode() * 31; }
- Success!:
-
Remove Element -------------- Element to be removed: customer id: 7, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Element to be removed: customer id: 4, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT removed customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT
- Note it only removes the “Puyol” object with the specified "customerId"; however, this is a business rules issue concerning the creation of "Customer" objects rather than a removal issue. "Customer" objects are equal if the "equals()" method returns true AND they have the same "hashCode()" value as objects with the same hash code may not be equal.
- What about a sorted set of objects? Strings have a natural order so we can simply change from a "HashSet" to a "TreeSet" without any other changes of code. However, there is no natural order associated with the "Customer" object. Changing to a "TreeSet" of "Customer" objects produces a runtime error:
-
run: Exception in thread "main" java.lang.ClassCastException: collections.Customer cannot be cast to java.lang.Comparable at java.until.TreeMap.compare(TreeMap.java:1290) at java.until.TreeMap.put(TreeMap.java:538) at java.until.TreeMap.add(TreeMap.java:255) at collections.Collections_Customer.addElements(Collections_Customer.java:55) at collections.Collections_Customer.main(Collections_Customer.java:30) Java Result: 1 BUILD SUCCESSFUL (total time: 0 seconds)
Set<Customer> customers = new TreeSet<>();
-
6.9 TreeSet of Objects
- An object class needs to implement the "Comparable" interface in order to add new elements of that class in the correct position. Let’s look at modifying the "Customer" class to handle this:
-
public class Customer implements Comparable<Customer> { @Override public int compareTo(Customer compareCustomer) { int custId = ((Customer) compareCustomer).getCustomerId(); //ascending order return this.customerId - custId; }
- This gives us a sorted set based on the ‘key’ field "customerId":
-
run: customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- What about sorting on different fields (or even combinations of fields)? In that case we need to create a "Comparator" to tell the "constructor/sort()" method how to sort the "Set/List"
-
public static Comparator<Customer> CustomerNameComparator = new Comparator<Customer>() { @Override public int compare(Customer cust1, Customer cust2) { String custName1 = cust1.getCustomerName(); String custName2 = cust2.getCustomerName(); //ascending order return custName1.compareTo(custName2); //descending order //return custName2.compareTo(custName1); } };
- Note this uses an anonymous class to implement / override the "compare()" method of the "Comparator" interface. Recall you cannot instantiate an Interface therefore a class must be instantiated and the interface method executed on that object. An anonymous class means that we do not have to name the class/object that is used to implement the interface and invoke the method. Lets create a new "TreeSet" object with elements from the original "TreeSet" using a "Comparator" for ordering:
-
System.out.println("Sort By Name"); System.out.println("------------"); Set<Customer> newSet = new TreeSet(Customer.CustomerNameComparator); newSet.addAll(customers); displayElements(newSet);
-
run: customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Sort By Name ------------ customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 5, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 4, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 6, customer name: Puyol, customer address: la Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- An alternative Collection interface is the List interface with concrete implementations: "ArrayList" and "LinkedList". Let’s look at changing the "Customer" collection from a "Set" to a "List":
-
List<Customer> customers = new ArrayList<>();
-
Add Elements ------------ toString ======== [customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT, customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT, customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT, customer id: 4, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT, customer id: 5, customer name: Pique, customer address: Barcelona, customer email: Gerard@barca.com, customer type: EXTERNAL_NOACCOUNT,customer id: 6, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT] for each ======== customer: customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer: customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer: customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer: customer id: 4, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer: customer id: 5, customer name: Pique, customer address: Barcelona, customer email: Gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer: customer id: 6, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT iterator ======== customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Pique, customer address: Barcelona, customer email: Gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 6, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- A "List" can hold duplicate elements and elements can also be inserted into a specific position. let’s create a "Customer" object and add it to the collection twice - at the start and the end of the collection
-
customers.add(new Customer("Iniesta", … )); … customers.add(new Customer("Pique", … )); Customer c = new Customer("Puyol", "La Pobla de Segur","charlie@barca.com",CustomerType.EXTERNAL_ACCOUNT); customers.add(c); customers.add(0, c);
- We can use the get() method to retrieve the element at the specified index position:
-
if (customers.get(0) == customers.get(5)) System.out.println( "Objects at positions 1 & 6 are equal" ); displayElements(customers);
-
Get --- Objects at position 1 & 6 are equal customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT
- The "indexOf()" method determines the index position of the first occurrence of the object and "lastIndexOf()" the last index position:
-
int index = customers.indexOf(c); System.out.println("Index: " + index); index = customers.lastIndexOf(c); System.out.println("Index: " + index);
-
customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Index of -------- customer id: 5, customer name: Puyole, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Index: 0 Last Index Of ------------- Index: 5
- We can remove an element by locating its index as above and using the "remove()" method or more commonly using an iterator to traverse the collection and test each element in turn for a match and then removing the element.
- A "List" is already ordered in the order in which elements have been inserted. The "sort()" method uses the natural order of objects as defined by the "compareTo()" method: Collections.sort(customers)
- The "sort()" method used in conjunction with a Comparator will sort by specific fields: customers.sort(Customer.CustomerNameComparator)
-
run: Add Elements ------------ customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Sort By Id ---------- customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 4, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT Sort By Name ------------ customer id: 3, customer name: Busquets, customer address: Sabadell, customer email: sergi@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 1, customer name: Iniesta, customer address: Fuentealbilla, customer email: andy@barca.com, customer type: INTERNAL_ACCOUNT customer id: 2, customer name: Messi, customer address: Rosario, customer email: lionel@barca.com, customer type: INTERNAL_ACCOUNT customer id: 4, customer name: Pique, customer address: Barcelona, customer email: gerard@barca.com, customer type: EXTERNAL_NOACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT customer id: 5, customer name: Puyol, customer address: La Pobla de Segur, customer email: charlie@barca.com, customer type: EXTERNAL_ACCOUNT