import java.util.HashMap;
import java.util.Map;
public class CompareCohorts {
public static void main(String[] args) {
CsCohort year1 = new CsCohort(2012, 132, .932);
CsCohort year2 = new CsCohort(2013, 172, .924);
CsCohort year3 = new CsCohort(2014, 157, .936);
CsCohort year4 = new CsCohort(2015, 172, .977);
System.out.println("The number of students still enrolled after one"
+ " year: " + year1.retained() + " in " + year1.getYear());
System.out.println("The number of students still enrolled after one"
+ " year: " + year2.retained() + " in " + year2.getYear());
System.out.println("The number of students still enrolled after one"
+ " year: " + year3.retained() + " in " + year3.getYear());
System.out.println("The number of students still enrolled after one"
+ " year: " + year4.retained() + " in " + year4.getYear());
year1.setRetainedPercent(0.95);
Map<String, CsCohort> theCohorts = new HashMap<>();
theCohorts.put("year1", year1);
theCohorts.put("year2", year2);
theCohorts.put("year3", year3);
theCohorts.put("year4", year4);
for (Map.Entry<String, CsCohort> entry : theCohorts.entrySet() ) {
if (entry.getValue().retained() > 150) {
System.out.println("More than 150 students for: " + entry.getKey());
System.out.println("which is: " + entry.getValue().getYear());
}
}
for (String key : theCohorts.keySet()) {
if (theCohorts.get(key).retained() > 150) {
System.out.println("More than 150 students for: " + key);
System.out.println("which is: " + theCohorts.get(key).getYear());
}
}
}
}
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:
String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'}; String str = new String(data);
Here are some more examples of how strings can be used:
System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2, 3); String d = cde.substring(1, 2);
The class String
includes methods for examining
individual characters of the sequence, for comparing strings, for
searching strings, for extracting substrings, and for creating a
copy of a string with all characters translated to uppercase or to
lowercase. Case mapping is based on the Unicode Standard version
specified by the Character
class.
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. For additional information on string concatenation and conversion, see The Java Language Specification.
Unless otherwise noted, passing a null
argument to a constructor
or method in this class will cause a NullPointerException
to be
thrown.
A String
represents a string in the UTF-16 format
in which supplementary characters are represented by surrogate
pairs (see the section Unicode
Character Representations in the Character
class for
more information).
Index values refer to char
code units, so a supplementary
character uses two positions in a String
.
The String
class provides methods for dealing with
Unicode code points (i.e., characters), in addition to those for
dealing with Unicode code units (i.e., char
values).
Unless otherwise noted, methods for comparing Strings do not take locale
into account. The Collator
class provides methods for
finer-grain, locale-sensitive String comparison.
javac
compiler
may implement the operator with StringBuffer
, StringBuilder
,
or java.lang.invoke.StringConcatFactory
depending on the JDK version. The
implementation of string conversion is typically through the method toString
,
defined by Object
and inherited by all classes in Java.We declare and initialise a HashMap here.
Notice that the left-hand side of the declaration
uses the Map
type, while the right-hand side uses the HashMap
type. We will talk about this when we talk about interfaces.
We declare and initialise a HashMap here.
Notice that the left-hand side of the declaration
uses the Map
type, while the right-hand side uses the HashMap
type. We will talk about this when we talk about interfaces.
We can access data stored within each object by calling its instance methods that expose that data.
In the code below, if we try to directly access data from the object, e.g., by writing year1.year
, our code would not compile. The year
variable is marked as private
in the CsCohort
class, so it is not visible here except through the public getYear
method.
We can access data stored within each object by calling its instance methods that expose that data.
In the code below, if we try to directly access data from the object, e.g., by writing year1.year
, our code would not compile. The year
variable is marked as private
in the CsCohort
class, so it is not visible here except through the public getYear
method.
print(String)
and then
println()
.print(String)
and then
println()
.x
- The String
to be printed.We can use the setter method to change the value of the year1
object's retainedPercent
field.
We can use the setter method to change the value of the year1
object's retainedPercent
field.
Console.charset()
if the Console
exists,
stdout.encoding otherwise.
Console.charset()
if the Console
exists,
stdout.encoding otherwise.
For simple stand-alone Java applications, a typical way to write a line of output data is:
System.out.println(data)
See the println
methods in class PrintStream
.
Here, we use the constructor from the CsCohort
class to create four
objects. Each object represents a cohort of students that entered the CS program.
Here, we use the constructor from the CsCohort
class to create four
objects. Each object represents a cohort of students that entered the CS program.
The new
keyword is used in Java to create new objects.
The new
keyword is used in Java to create new objects.
This is the data type of each element in the entry set. It looks a little
wonky, so here's what each part is saying. The Map.Entry
part says that
Entry
is an internal class within the Map
class (i.e., a class within a class; sometimes this is okay). The
<String, CsCohort>
part says that each map entry, like the map itself,
has a key of type String
and a value of type CsCohort
.
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
This is the data type of each element in the entry set. It looks a little
wonky, so here's what each part is saying. The Map.Entry
part says that
Entry
is an internal class within the Map
class (i.e., a class within a class; sometimes this is okay). The
<String, CsCohort>
part says that each map entry, like the map itself,
has a key of type String
and a value of type CsCohort
.
This interface takes the place of the Dictionary
class, which
was a totally abstract class rather than an interface.
The Map
interface provides three collection views, which
allow a map's contents to be viewed as a set of keys, collection of values,
or set of key-value mappings. The order of a map is defined as
the order in which the iterators on the map's collection views return their
elements. Some map implementations, like the TreeMap
class, make
specific guarantees as to their order; others, like the HashMap
class, do not.
Note: great care must be exercised if mutable objects are used as map
keys. The behavior of a map is not specified if the value of an object is
changed in a manner that affects equals
comparisons while the
object is a key in the map. A special case of this prohibition is that it
is not permissible for a map to contain itself as a key. While it is
permissible for a map to contain itself as a value, extreme caution is
advised: the equals
and hashCode
methods are no longer
well defined on such a map.
All general-purpose map implementation classes should provide two
"standard" constructors: a void (no arguments) constructor which creates an
empty map, and a constructor with a single argument of type Map
,
which creates a new map with the same key-value mappings as its argument.
In effect, the latter constructor allows the user to copy any map,
producing an equivalent map of the desired class. There is no way to
enforce this recommendation (as interfaces cannot contain constructors) but
all of the general-purpose map implementations in the JDK comply.
The "destructive" methods contained in this interface, that is, the
methods that modify the map on which they operate, are specified to throw
UnsupportedOperationException
if this map does not support the
operation. If this is the case, these methods may, but are not required
to, throw an UnsupportedOperationException
if the invocation would
have no effect on the map. For example, invoking the putAll(Map)
method on an unmodifiable map may, but is not required to, throw the
exception if the map whose mappings are to be "superimposed" is empty.
Some map implementations have restrictions on the keys and values they
may contain. For example, some implementations prohibit null keys and
values, and some have restrictions on the types of their keys. Attempting
to insert an ineligible key or value throws an unchecked exception,
typically NullPointerException
or ClassCastException
.
Attempting to query the presence of an ineligible key or value may throw an
exception, or it may simply return false; some implementations will exhibit
the former behavior and some will exhibit the latter. More generally,
attempting an operation on an ineligible key or value whose completion
would not result in the insertion of an ineligible element into the map may
throw an exception or it may succeed, at the option of the implementation.
Such exceptions are marked as "optional" in the specification for this
interface.
Many methods in Collections Framework interfaces are defined
in terms of the equals
method. For
example, the specification for the containsKey(Object key)
method says: "returns true
if and
only if this map contains a mapping for a key k
such that
(key==null ? k==null : key.equals(k))
." This specification should
not be construed to imply that invoking Map.containsKey
with a non-null argument key
will cause key.equals(k)
to
be invoked for any key k
. Implementations are free to
implement optimizations whereby the equals
invocation is avoided,
for example, by first comparing the hash codes of the two keys. (The
Object.hashCode()
specification guarantees that two objects with
unequal hash codes cannot be equal.) More generally, implementations of
the various Collections Framework interfaces are free to take advantage of
the specified behavior of underlying Object
methods wherever the
implementor deems it appropriate.
Some map operations which perform recursive traversal of the map may fail
with an exception for self-referential instances where the map directly or
indirectly contains itself. This includes the clone()
,
equals()
, hashCode()
and toString()
methods.
Implementations may optionally handle the self-referential scenario, however
most current implementations do not do so.
The Map.of
,
Map.ofEntries
, and
Map.copyOf
static factory methods provide a convenient way to create unmodifiable maps.
The Map
instances created by these methods have the following characteristics:
UnsupportedOperationException
to be thrown.
However, if the contained keys or values are themselves mutable, this may cause the
Map to behave inconsistently or its contents to appear to change.
null
keys and values. Attempts to create them with
null
keys or values result in NullPointerException
.
IllegalArgumentException
.
This interface is a member of the Java Collections Framework.
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:
String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'}; String str = new String(data);
Here are some more examples of how strings can be used:
System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2, 3); String d = cde.substring(1, 2);
The class String
includes methods for examining
individual characters of the sequence, for comparing strings, for
searching strings, for extracting substrings, and for creating a
copy of a string with all characters translated to uppercase or to
lowercase. Case mapping is based on the Unicode Standard version
specified by the Character
class.
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. For additional information on string concatenation and conversion, see The Java Language Specification.
Unless otherwise noted, passing a null
argument to a constructor
or method in this class will cause a NullPointerException
to be
thrown.
A String
represents a string in the UTF-16 format
in which supplementary characters are represented by surrogate
pairs (see the section Unicode
Character Representations in the Character
class for
more information).
Index values refer to char
code units, so a supplementary
character uses two positions in a String
.
The String
class provides methods for dealing with
Unicode code points (i.e., characters), in addition to those for
dealing with Unicode code units (i.e., char
values).
Unless otherwise noted, methods for comparing Strings do not take locale
into account. The Collator
class provides methods for
finer-grain, locale-sensitive String comparison.
javac
compiler
may implement the operator with StringBuffer
, StringBuilder
,
or java.lang.invoke.StringConcatFactory
depending on the JDK version. The
implementation of string conversion is typically through the method toString
,
defined by Object
and inherited by all classes in Java.The main method is the entry point for our program. It is the method that is called when we run the CompareCohorts
class.
It is important for all parts of this method signature to be present, otherwise it will not be treated as the entry point.
We will talk about the meaning of static
in the next lesson.
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
The main method is the entry point for our program. It is the method that is called when we run the CompareCohorts
class.
It is important for all parts of this method signature to be present, otherwise it will not be treated as the entry point.
We will talk about the meaning of static
in the next lesson.
String
class represents character strings. All
string literals in Java programs, such as "abc"
, are
implemented as instances of this class.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:
String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'}; String str = new String(data);
Here are some more examples of how strings can be used:
System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2, 3); String d = cde.substring(1, 2);
The class String
includes methods for examining
individual characters of the sequence, for comparing strings, for
searching strings, for extracting substrings, and for creating a
copy of a string with all characters translated to uppercase or to
lowercase. Case mapping is based on the Unicode Standard version
specified by the Character
class.
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. For additional information on string concatenation and conversion, see The Java Language Specification.
Unless otherwise noted, passing a null
argument to a constructor
or method in this class will cause a NullPointerException
to be
thrown.
A String
represents a string in the UTF-16 format
in which supplementary characters are represented by surrogate
pairs (see the section Unicode
Character Representations in the Character
class for
more information).
Index values refer to char
code units, so a supplementary
character uses two positions in a String
.
The String
class provides methods for dealing with
Unicode code points (i.e., characters), in addition to those for
dealing with Unicode code units (i.e., char
values).
Unless otherwise noted, methods for comparing Strings do not take locale
into account. The Collator
class provides methods for
finer-grain, locale-sensitive String comparison.
javac
compiler
may implement the operator with StringBuffer
, StringBuilder
,
or java.lang.invoke.StringConcatFactory
depending on the JDK version. The
implementation of string conversion is typically through the method toString
,
defined by Object
and inherited by all classes in Java.The signature of a method is composed of its name, parameter list, return type, and any modifiers like public
and static
. The first two components (name and parameter list)together will uniquely identify a method within a class. I.e., there can never exist multiple methods in one class with the same name and parameter types.
The signature of a method is composed of its name, parameter list, return type, and any modifiers like public
and static
. The first two components (name and parameter list)together will uniquely identify a method within a class. I.e., there can never exist multiple methods in one class with the same name and parameter types.
HashMap
with the default initial capacity
(16) and the default load factor (0.75).Map
interface. This
implementation provides all of the optional map operations, and permits
null
values and the null
key. (The HashMap
class is roughly equivalent to Hashtable
, except that it is
unsynchronized and permits nulls.) This class makes no guarantees as to
the order of the map; in particular, it does not guarantee that the order
will remain constant over time.
Map
interface. This
implementation provides all of the optional map operations, and permits
null
values and the null
key. (The HashMap
class is roughly equivalent to Hashtable
, except that it is
unsynchronized and permits nulls.) This class makes no guarantees as to
the order of the map; in particular, it does not guarantee that the order
will remain constant over time.
This implementation provides constant-time performance for the basic
operations (get
and put
), assuming the hash function
disperses the elements properly among the buckets. Iteration over
collection views requires time proportional to the "capacity" of the
HashMap
instance (the number of buckets) plus its size (the number
of key-value mappings). Thus, it's very important not to set the initial
capacity too high (or the load factor too low) if iteration performance is
important.
An instance of HashMap
has two parameters that affect its
performance: initial capacity and load factor. The
capacity is the number of buckets in the hash table, and the initial
capacity is simply the capacity at the time the hash table is created. The
load factor is a measure of how full the hash table is allowed to
get before its capacity is automatically increased. When the number of
entries in the hash table exceeds the product of the load factor and the
current capacity, the hash table is rehashed (that is, internal data
structures are rebuilt) so that the hash table has approximately twice the
number of buckets.
As a general rule, the default load factor (.75) offers a good
tradeoff between time and space costs. Higher values decrease the
space overhead but increase the lookup cost (reflected in most of
the operations of the HashMap
class, including
get
and put
). The expected number of entries in
the map and its load factor should be taken into account when
setting its initial capacity, so as to minimize the number of
rehash operations. If the initial capacity is greater than the
maximum number of entries divided by the load factor, no rehash
operations will ever occur.
If many mappings are to be stored in a HashMap
instance, creating it with a sufficiently large capacity will allow
the mappings to be stored more efficiently than letting it perform
automatic rehashing as needed to grow the table. Note that using
many keys with the same hashCode()
is a sure way to slow
down performance of any hash table. To ameliorate impact, when keys
are Comparable
, this class may use comparison order among
keys to help break ties.
Note that this implementation is not synchronized.
If multiple threads access a hash map concurrently, and at least one of
the threads modifies the map structurally, it must be
synchronized externally. (A structural modification is any operation
that adds or deletes one or more mappings; merely changing the value
associated with a key that an instance already contains is not a
structural modification.) This is typically accomplished by
synchronizing on some object that naturally encapsulates the map.
If no such object exists, the map should be "wrapped" using the
Collections.synchronizedMap
method. This is best done at creation time, to prevent accidental
unsynchronized access to the map:
Map m = Collections.synchronizedMap(new HashMap(...));
The iterators returned by all of this class's "collection view methods"
are fail-fast: if the map is structurally modified at any time after
the iterator is created, in any way except through the iterator's own
remove
method, the iterator will throw a
ConcurrentModificationException
. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than risking
arbitrary, non-deterministic behavior at an undetermined time in the
future.
Note that the fail-fast behavior of an iterator cannot be guaranteed
as it is, generally speaking, impossible to make any hard guarantees in the
presence of unsynchronized concurrent modification. Fail-fast iterators
throw ConcurrentModificationException
on a best-effort basis.
Therefore, it would be wrong to write a program that depended on this
exception for its correctness: the fail-fast behavior of iterators
should be used only to detect bugs.
This class is a member of the Java Collections Framework.
We use this class as our "driver", i.e., it contains the entry point for our overall program. This class is responsible for creating the objects that we will use to store our data.
Although we don't intend to create instances of the CompareCohorts
class, we still need to wrap this code inside a class, because all Java code must be run inside a class. So it goes.
We use this class as our "driver", i.e., it contains the entry point for our overall program. This class is responsible for creating the objects that we will use to store our data.
Although we don't intend to create instances of the CompareCohorts
class, we still need to wrap this code inside a class, because all Java code must be run inside a class. So it goes.
We can also iterate over the map using the keySet
method.
This method returns a set of all the keys in the map.
By looping over the set of keys, we can obtain all the values one at a time.
We can also iterate over the map using the keySet
method.
This method returns a set of all the keys in the map.
By looping over the set of keys, we can obtain all the values one at a time.
We use the put
method to add data to the map.
The first argument is the key, and the second argument is the value.
Duplicate keys are not allowed; if you add an object using a key that already
exists in the map, the old value will be overwritten with the new value.
We use the put
method to add data to the map.
The first argument is the key, and the second argument is the value.
Duplicate keys are not allowed; if you add an object using a key that already
exists in the map, the old value will be overwritten with the new value.
We use the entrySet
method to get a set of all the key-value pairs
in the map. We can then iterate over the set using a for-each loop.
We use the entrySet
method to get a set of all the key-value pairs
in the map. We can then iterate over the set using a for-each loop.