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.








