Unit 10 Sets and Maps Flashcards
Sets:-
Consider the following statement that declares and creates a new set of strings:
Set < String > herbSet = new HashSet < String > ( );
Answer the following questions:
(a) What is the purpose of < String > , which occurs twice in the above statement?
(b) Given an initial decision to use HashSet, why should the instance of HashSet be referenced by avariable of type Set?
(c) Given an initial decision for herbSet to be of type Set, why should the HashSet class be used?
(a) The first occurrence of in this statement is used in the declaration of the variable herbSet. It specifies that herbSet can only be used to reference a set whose element type is String. The second occurrence of is used with the HashSet constructor and the keyword new to create a set with the element type of String.
(b) It is good practice, where possible, to declare the variable in terms of an interface type (here Set), not the type of the implementing class (here HashSet). This promotes flexibility and hence maintainability.
(c) If we require a class that implements the Set interface and have no other information on which to base our choice, HashSet is a good general-purpose choice.
Sets:-
Set < String > herbSet = new HashSet < > ( );
This statement can not compile successfully unless we also tell the compiler where to find the definitions for both the Set interface and the HashSet class, so any class in which the statement above appears will have to import these definitions from the appropriate java package. The simplest approach is to import the whole package with the statement: import java.\_\_\_\_\_\_
import java.util.*
Sets:-
One of the simplest things you can do with a set is to test its size. This can be done using the message ______( ). As you might expect, the size of a newly created empty set is 0.
Our first example illustrates this:
Set < String > herbSet = new HashSet < > ( );
int size = herbSet.______( );
System.out.println(“The size of the newly created set is “ +size);
When executed, the above code prints the string “The size of the newly created set is 0” in the Display Pane.
size( )
thereforethe code should read:
Set < String > herbSet = new HashSet < >( );
int size =herbSet.size();
System.out.println(“The size of the newly created set is “ +size);
size( ) is a testing method which means it does not alter the set, just reports on it.
public int size()
Category testing
Returns the number of elements in the receiver.
Sets:-
We can add elements to a set, one at a time, with the message ______(), as demonstrated by the following code:
Set < String > herbSet = new HashSet < String > ( );
herbSet.______(“Parsley”);
herbSet.______(“Sage”);
herbSet.______(“Rosemary”);
System.out.println(“Size after adding elements: “ +herbSet.size( ));
Note we can only add elements that are type compatible with the declared element type of the variable herbSet.
add( )
Set < String > herbSet = new HashSet < String > ( );
herbSet.add(“Parsley”);
herbSet.add(“Sage”);
herbSet.add(“Rosemary”);
System.out.println(“Sizeafter addingelements: “ +herbSet.size( ));
public boolean add(ElementType obj)
Category adding
Adds the argument to the receiver, unless it is already there. Returns true if the argument was added, false if it was not.
Sets:-
Set < String > herbSet =new HashSet < > ( );
herbSet.add(“Parsley”);
herbSet.add(“Sage”);
herbSet.add(“Rosemary”);
herbSet.add(“Rosemary”);
herbSet.add(“Rosemary”);
System.out.println(“Size of herbSet: “ +herbSet.size( ));
what value will be returned?
A distinctive behaviour of sets is that the same element can not appear twice. If an attempt is made to add an element already present, the state of the set is left unaltered. The code sample demonstrates this.
Although add() is used five times, there are only three distinct elements involved and consequently the final size is 3 not 5.
The code displays:
Size of herbSet: 3
Sets:-
isEmpty () to determine whether a set isEmpty of elements - what variable result value will the code assign:
Set < String > herbSet =new HashSet < String >( );
boolean result;
herbSet.add(“Parsley”);
herbSet.add(“Sage”);
herbSet.add(“Rosemary”);
result = herbSet.isEmpty();
What value is returned?
In the code, the variable result is assigned the value false.
isEmpty() is a testing method, same as size() and contains()
public boolean isEmpty()
Category testing
Returns true if the set is empty, otherwise false.
Sets:-
contains() to determine whether a set includes a particular element - what variable result value will the code assign:
Set < String > herbSet = new HashSet < >( );
herbSet.add(“Parsley”);
herbSet.add(“Sage”);
herbSet.add(“Rosemary”);
result =herbSet.contains(“Sage”);
In the code, the variable result is assigned the value true.
contains() is a testing method, same as size() and isEmpty()
public boolean contains(Object obj)
Category testing
Returns true if the argument is an element in the receiver, false if not.
Sets:
Diamond operators and Java versions:-
Which of the following code would compile using Java 7?
(a) Set < String > herbSet = new HashSet < String > ( );
(b) Set < String > herbSet =new HashSet < >( );>
both
from Java7 onward the right-hand-side diamond operators can be left empty as Java will automatically know it is the same element type as the left-hand-side
Sets:
Diamond operators and Java versions:-
Which of the following code would compile using Java 6?
(a) Set < String > herbSet = new HashSet < String > ( );
(b) Set < String > herbSet = new HashSet < >( );
only (a)
it was only since Java version 7 onward you can leave the right-hand-side diamond operators empty
Sets:-
Will this compile?
Set < String > herbSet = new HashSet ( );
yes
However, firstly, it is bad practice to omit the diamond operator altogether.
The code should generate a compiler warning about an unchecked or unsafe operation because it creates a collection without specifying a type of element that the collection will hold. This style of declaration was used before Java5.
Such warnings are suppressed in theOUWorkspace. For backward compatibility reasons, the designers of Java still allow these raw collections to be used, but the compiler for later versions of Java may warn you if you do so because these earlier collections did not provide the same level of type checking as the new ones do.
Secondly, it is important to note that a lot of existing code you may encounter elsewhere will have been written before Java 7, and will not use the diamond operator. Thus it helps to be able to read and write such code. Because of this, both approaches are in the module.
Sets:-
What is the message to remove an element from a set object to produce the message answer true if its argument was found and removed, and false if it was not found.
Set < String > herbSet = new HashSet < > ( );
herbSet.add(“Parsley”);
herbSet.add(“Sage”);
herbSet.add(“Rosemary”);
boolean removed =herbSet.______(“Parsley”);
if (removed)
{
OUDialog.alert(“Herb removed”);
}
else
{
OUDialog.alert(“Herb not found”);
}
remove( )
These message replies can be very useful. For example, if an element cannot be removed because it was not present, then for some applications it might be important to take some action such as warning the user, as illustrated by the code.
public boolean remove(Object obj)
Category removing
If the argument is an element in the receiver it is removed from the receiver and the method returns true. If the argument is not an element in the receiver, the receiver remains unchanged and the method returns false.
Sets:-
Will the following code compile?
Set < int > numSet = new HashSet < > ( );
The code is not legal so will not compile
When introduced to sets we have focused on sets of < String > , but you can create sets containing different element types in the same way. However, sets must hold references to objects; the element type can not be int or any other primitive data type.
Sets:-
Due to Sets only allowing Reference data types, such as <string> we can not use <strong><int></int></strong>, we need to rely on a <strong>Wrapper Class</strong>. In this case, for int, the wrapper class name is \_\_\_\_\_\_.</string>
Integer
Luckily, for every primitive type, there is a corresponding class of objects we can use to ‘wrap’ values of that type. Otherwrapper classes are Long, Float, Double, Short, Byte, Character, and Boolean.The corresponding primitive data types will be clear from the names, but note that char is spelled out in full as Character.
Wrapper classes are quite simple library classes that provide an object-oriented version of primitive types.
Sets:-
Wrap and UnWrap
create an instance of Integer, with the variable name wrappedNum to wrap the primitive value 7
Integer wrappedNum = new Integer (7);
using the Integer class constructor with the value you want to wrap as an argument. You can extract (we also say ‘unwrap’) the primitive value again like this:
int unwrappedNum = wrappedNum.intValue();
using the intValue() method of the Integer class, which returns an int
Sets:-
Wrapping
Integer wrappedNum = new Integer (7);
and unwrapping
int unwrappedNum = wrappedNum.intValue();
is fairly straightforward, but when we use numbers we generally want to do arithmetic with them.The arithmetic cannot in general be carried out on the Integer objects directly, so we have to unwrap the primitive values first, then do the calculation, and then wrap the answer back up again. This can involve a lot of programming overhead. However, in early versions of Java there was no other option.
Until Java 1.5 onwards, the wrapping is done for us automatically. This is called _______ and the unwrapping is called _______
auto-boxing and auto-unboxing
allowing us to write code such as:
- Set < integer > myNumbers = new HashSet < integer > ( );*
- myNumbers.add(7)*
the compiler will translate the second statement into bytecode that takes care of everything for us. It is as though primitive values can be added directly into the collection – although really, behindthe scenes, wrapper objects are being used.
Sets:-
Consider a set declared as follows:
Set< Integer > numSet = new HashSet < > ( );
We can add some primitive int values to this set as follows:
numSet.add(5);
numSet.add(6);
numSet.add(5);
The effect of evaluating these statements will be that the primitive values will be boxed as Integers automatically before they are added to the set.
What will the class of each element of numSet be after the above statements have been evaluated?
The class of each element of numSet will be Integer
Sets:-
Using paper and pencil
/**
*Demonstrates the creation of a set of Integers and
*the subsequent adding and removing of elements.
*/
Set < Integer >numberSet = new HashSet < > ( );
int anInt = 4;
numberSet.add(anInt);
//try different integer values for anInt
numberSet.add(1);
numberSet.add(4);
numberSet.add(5);
numberSet.remove(6);
numberSet.remove(1);
Suppose the above example code is evaluated on three different occasions, each time using a different value of anInt as follows:
(1) anInt = 1;
(2) anInt = 6;
(3) anInt = 2;
For each case, describe the resulting state of numberSet.
After anInt = 1;
<1> | <1> | <1,4> | <1,4,5> | false | true <4,5>
the set contains Integer objects that wrap the int values 4 and 5. <4,5>
_____________________________
After anInt = 6;
<6>| <6,1> | <6,1,4> | <6,1,4,5> | true <1,4,5>| true <4,5>
the set contains Integer objects that wrap the int values 4 and 5. <4,5>
_____________________________
After anInt = 2;
<2> | <2,1> | <2,,4> | <2,1,4,5> | false | true <2,4,5>
the set contains Integer objects that wrap the int values 2, 4 and 5. <2,4,5>
Sets:-
Set < Integer >numSet = new HashSet< > ( );
numSet.add(12);
numSet.add(9);
numSet.add(88);
Write a for-each statement to print out the sum of the numbers
one such statement could be:
inttotal = 0;
for (Integer eachNum : numSet)
{
total =total +eachNum;
}
System.out.println (“Sum of all elements: “ +total);
Sets:-
If a for-each statement declares its local variable with the identifier each instead of eachNum, would there be a compilation error?
for (Integer each : numSet)
No, any valid identifier can be used for a for-each statement’s local variable. However, you might want to argue that calling the variable eachNum (or eachAccount, eachHerb or eachName) makes it easier for the human reader to understand what is happening.
Sets:- Given the code:
- Set < Integer > numSet =new HashSet< >();*
- numSet.add(12);*
- numSet.add(9);*
- numSet.add(88);*
- inttotal = 0;*
- for (Integer eachNum : numSet)*
- {*
- total =total +eachNum;*
- }*
- System.out.println (“Sum of all elements: “ +total);*
(a) Why has the for-each statement’s local variable eachNum been declared to be of the Integer class, when the code prior tothe foreach statement has been adding values of the primitive type int to the set?
(b) In a HashSet, can we predict with certainty in what order the elements will be iterated over?
(a) The variable numSet was declared as type Set, so eachNum was declared to match the element type. All the elements in the set are instances of the Integer class. However, auto-boxing allows you to use the type int for the variable numSet as well.
(b) No. The order is undefined and there is no way to predict it. see below from Java Docs
public class HashSet extends AbstractSet
implements Set, Cloneable, Serializable
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
Sets:-
Is it possible to use itertion (for-each loop) to remove elements or replace elements?
no, more advance techniques are needed.
Sets:-
Just as with arrays, it is possible to iterate through a set using a hand-coded for loop instead of a for-each loop. However, for a set this is less straightforward. With an array we can simply use an int counter to represent the numerical index of each element in turn, and increment the index each time the loop is executed.
Why will this plan, which works for an array, not work for a set?
Remember, sets are dynamic, allow no dupliates, not indexed and generally unordered…
Sets have no index and so there is simply no way to access the elements of a set using an integer counter. You can however (just not in this modue) iterate over a set after obtaining an instance of an Iterator, using the set’s iterator() method.
Sets:-
The following example code creates a set of strings with each element being the name of a herb. The last line of the code then prints the size of the set to the standard output.
Set < String >herbSet = new HashSet< >( );
herbSet.add(“camomile”);
herbSet.add(“rosemary”);
herbSet.add(“basil”);
herbSet.add(“thyme”);
herbSet.add(“mint”);
herbSet.add(“sage”);
herbSet.add(“lovage”);
herbSet.add(“parsley”);
herbSet.add(“chives”);
herbSet.add(“marjoram”);
System.out.println(herbSet.size());
What if, instead of printing out the size of the set, we wanted to print out the contents of the set, string-by-string?
Using the above code, create a modified version of the code as follows: Within the statement block of a for-each statement the code should printout to the Display Pane the name of each herb. You don’t need to write the code to add() the herbs just the for-each statement
for (String herb: herbSet)
{
System.out.println(herb);
}
Sets:-
If we wanted to print out the herbSet alphabetically, how could you modify the code below:- hint: not much needs altering
Set < String > herbSet = new HashSet < > ( );
herbSet.add(“camomile”);
herbSet.add(“rosemary”);
herbSet.add(“basil”);
herbSet.add(“thyme”);
herbSet.add(“mint”);
herbSet.add(“sage”);
herbSet.add(“lovage”);
herbSet.add(“parsley”);
herbSet.add(“chives”);
herbSet.add(“marjoram”);
for (String herb: herbSet)
{
System.out.println(herb);
}
Set < String >herbSet = new HashSet< >( );
becomes
Set < String >herbSet = new TreeSet< >( );
Told you it wasn’t much!
The herbs will now automatically be in order. This begins to illustrate some of the power of the Java Collections Framework.
Maps:-
Maps are a collection with keys and values.
True or False:
key (what you find there) and value (the thing you look up)
False
rosehip 42
raspberry 32 & 76
mango and ginseng 18
This extract from a book index has entries consisting of a key (the thing you look up) and a value (what you find there).
For example, 42 is the value corresponding to the key ‘rosehip’. This way of structuring information is the motivation behind the collection known as a map.
Maps:-
Why can’t we “Map” books by a Key being represented by the Books Title and the Value being represented by the books available format :
Key — Value
The Shining — Hardback, Paperback, Audio, EBook
How to become successful — Hardback, Paperback, Audio, EBook
Beginners Guide To Beer — Hardback, Paperback, EBook
My Saucy Sauces — EBook
The Value is legal as it is ok not to be unique. more than one author has a paperback and EBook.
The Key must be unique. There will be more than one book called “How to become Successful”
Consequently, merely knowing the book title and author of a book is not always enough to identify uniquely a specific edition. Hence, for the purpose of identifying book editions, book title and author alone would not make a sensible key.
A better way of uniquely identifying book editions is the International Standard Book Number ( ISBN ).
(Note though that the ISBN would be no good as a key for distinguishing your copy of the same edition from my copy of the same edition because they will both have the same ISBN. So what makes a good key depends on your purposes. It depends on exactly what you need to distinguish.)
Maps:-
For each of the following, say whether or not it makes an acceptable key. If you think it would, suggest what kind of value the key might be associated with.
(a) A staff ID number for employees in a company.
(b) The name of your Open University (OU) tutor amongst the body of OU tutors.
(c) Your OU student identifier amongst all OU students.
(a) This would normally be a unique key. Examples of appropriate values include an employment record or personnel file.
(b) This choice of key is not acceptable because it is possible that some OU tutors may have the same name. ( If tutor names were unique, a likely value for this key would be a tutorial group.)
(c) This is a unique key. The value might be, for example, marks for a given module or the student record.
In summary, when devising any scheme for keys for objects in some group, the vital consideration is that each key should be unique within the collection.
Maps:-
Assuming that the name is the key, which of the two following telephone directories is suitable for representing directly as a map? Give a reason for your answer.
((see image)
There is no problem with Directory A. Noggin the Nog and Queen Nooka are two keys with the same value, but this is perfectly allowable for maps.
Directory B can not be used directly as a map, since Pirate Jake’s name is not unique in this directory, and so names cannot act as unique keys for extension numbers.
We could get round this by changing the type of the values to be stored in the map from individual extension numbers into sets of extension numbers. Thus, Pirate Jake could still have two telephone numbers while everyone else had a single number, but now each key would have a single value, which is a set of numbers, even though the majority of sets just had one number in them. This approach is illustrated in the following table.
Name — Telephone number
Capt Pugwash — 6001
Tom the Cabin Boy — 5204
Pirate Jake — 0667, 0668
Maps:-
When creating a set we had to specify the type of the elements that would be stored in it. Before creating an instance of a map, it is necessary to specify two things:
the type of the keys and the type of the values to be stored.
Can these be different from each other?
Yes
For example, to keep track of customers’ bank accounts, you might use strings containing account numbers as keys and instances of Account as values. Or Integer ISBN numbers and String formats for library books.
Maps:-
Map < String, Account > accounts = new HashMap < String, Account > ( );
or
Map < String, Account > accounts = new HashMap < > ( );
In the above statements, the declared type of the variable accounts is Map, while its implementing class is HashMap.
Explain why…
As we noted with Set, it is generally good practice to use a collection interface as the type of the variable. This promotes flexibility and maintainability. It was this choice that allowed us in Sets to change a HashSet to a TreeSet without changing the reference variable type.