SlideShare a Scribd company logo
1
Nico Ludwig (@ersatzteilchen)
Collections – Part IV
2
2
●
Collections – Part IV
– Object-based vs. generic Collections
●
Generics Types in Java
– Sequential and associative Collections
– Associative Collections
●
Equivalence-based associative Collections: .Net's SortedDictionary
●
Operations on .Net's IDictionarys
●
Comparison and Implementation of .Net's Interfaces IComparable and IComparer
TOC
3
3
●
Explicitly typed – i.e. typenames must be explicitly written at their declaration:
●
Safely typed – i.e. unrelated types can't fool the compiler.
– Cross casting and other pointer stuff is generally illegal.
●
Statically typed – i.e. variables' types are determined at compile time:
●
Sorry? But the same variable can hold different sub type objects at run time!
– Indeed! We can define variables that may hold e.g. any derived type:
– .Net differs the static (Object) and the dynamic type (Car) of an instance.
– The idea of static/dynamic types is used for run time polymorphism in .Net.
double sum = 5.2; // Type name "double" must be explicitly written for the variable sum.
int count = 42; // count is of type int, we can only perform int operations on it!
Object o = new Car(); // Type Car is derived from type Object.
The Type System in .Net 1 (presented in C#1) – Part I
4
4
●
Esp. object-based collections rely on the cosmic hierarchy of .Net's type system: everything is an Object:
– .Net 1 collections: Hold items of static type Object, their dynamic types can vary.
●
In fact collections must be able to hold any type in order to be versatile.
– .Net 1 "resorted" to run time polymorphism (i.e. Liskov Substitution Principle (LSP)) to get this versatility.
– So in a .Net 1 collection, objects of any dynamic type can be stored.
●
Object-based collections work great, as long as...
– we'll only store objects of dynamic types that dependent code awaits,
– we'll only cast down to dynamic types that dependent code put in,
– we'll never put mixed unrelated dynamic types into the same collection,
– well as we don't fall into a type problem during run time.
ArrayList lines = new ArrayList(File.ReadAllLines("/Library/Logs/Software Update.log")); // File.ReadAllLines() was introduced with .Net 2!
object item1 = lines[0];
object item2 = lines[1];
// We have to use cast contact lenses to get the dynamic types out of the objects:
string text1 = (string)item1;
// Access string's interface:
int result = text1.IndexOf('g');
// We can also cast directly from the index notation:
string text2 = (string)lines[1];
The Type System in .Net 1 (presented in C#1) – Part II
5
5
●
The problem or lack in the type system using LSP can be presented with the just created collectionlines:
●
The problem is that we as programmers have to know about the contained dynamic types (strings and not Cars in lines).
– Whenever Object is used in an interface (the return value of lines' indexer), some convention must be around.
– This convention describes the dynamic type, we're really dealing with (strings and not Cars).
– The contributed programers have just to obey the convention... ;-)
●
We as programmers have to cast down (or unbox) to the type we await.
– The cast is needed to access the interface of a static type (e.g. car.StartEngine()).
– These casts indicate that the programer knows more than the compiler!
– The compiler wears "cast contact lenses"; it can't type check, it trusts the programmer!
– These casts are type checked at run time, so they are consuming run time!
– Type errors (an item of lines was casted to Car instead of string) will happen at run time, not at compile time.
object item1 = lines[0];
// But, these are not the awaited types, we can't deal with Cars, we await strings!
// This cast will fail! An InvalidCastException will be thrown!
Car car = (Car)item1;
car.StartEngine();
public class Car {
public void StartEngine() {
/* pass */
}
}
The Type System in .Net 1 (presented in C#1) – Part III
6
6
●
Object-based collections have an interesting feature: we can beheterogeneous collections:
– In a heterogeneous collection every item can have any different dynamic type:
●
It works, but heterogeneous collections are tricky: developers need to know, on which indexes objects of certain types
reside.
●
Heterogenous collection should be avoided! Strive to using homogenous collections or other solutions!
ArrayList objects = new ArrayList();
// Since each item is of type object, we can add any object to an ArrayList:
objects.Add("aString"); // String
objects.Add(42); // int
objects.Add(new object()); // object
objects.Add(new [] {1, 2, 3, 4}); // int[]
foreach(object item in objects) {
Console.WriteLine(item);
}
// This statement will fail, we can't deal with string, on index 1 an int was stored!
// An InvalidCastException will be thrown!
string result = (string)objects[1];
Homogeneous and heterogeneous Collections
7
7
●
What could we do close the lack in the .Net 1 type system to stay typesafe?
●
We could use strictly typed arrays as collections if possible, they're not object-based and therefore typesafe:
– However, arrays can not be used, when the collection in question needs to be modified (enlarged or downsized) after creation.
●
We could create own, typesafe not object-based collections as UDTs (e.g. a special string-list for the discussed example).
– In .Net we could resort to so called specialized collections in the namespace System.Collections.Specialized, e.g. StringCollection.
●
But in the world of collections, there is a much better way to work in a typesafe manner: generic collections!
// Create an array that hold strings:
string[] lines = File.ReadAllLines("/Library/Logs/Software Update.log"));
// With arrays we don't need casts, instead we can directly access lines' items as string objects:
string text1 = lines[0];
// Access string's interface:
int result = text1.IndexOf('g');
// Create a specialized StringCollection:
StringCollection lines = new StringCollection();
lines.AddRange(File.ReadAllLines("/Library/Logs/Software Update.log"));
// With the specialized StringCollection we don't need casts, instead we can directly access lines' items as string objects:
string text1 = lines[0];
// Access string's interface:
int result = text1.IndexOf('g');
The Type System in .Net 1 – Some Remedy
8
8
●
Let's improve our problematic code with the generic collection List<T>:
●
.Net 2 introduced generic types to get rid of the presented type problems.
– Generic types are types that leave a part of their type information open.
– Generics are an outstanding feature in .Net 2.
●
Generics (here List<T>) leave type information open? How should this help me out?
– The open type information is accessible by type parameters (here T).
– As programmers we can fill the type parameters by concrete type arguments (here string).
– By setting type arguments of a generic type we create another type, the constructed type (List<string> in this case).
●
The full name of the constructed type is List<string>!
– => Net effect: The type argument (string) will be of static type, so the formerly open type information can be checked by the compiler.
– In the end typesafety means that types are checked by the compiler at compile time and no longer at run time.
// Create a generic List that holds strings:
List<string> lines = new List<string>(File.ReadAllLines("/Library/Logs/Software Update.log"));
// This time we don't need casts, instead we can directly access lines' items as string objects:
string text1 = lines[0];
// Access string's interface:
int result = text1.IndexOf('g');
// The generic type List<T>:
public class List<T> { // (members hidden)
public void Add(T item) {
/* pass */
}
}
// This time we'll get a compile time error:
Car car1 = lines[1];
// The type argument in lines was string, not Car!
// Cannot convert string to Car.
car1.StartEngine();
Generics to the Rescue
9
9
●
.Net's generic collections live in the namespace System.Collections.Generic.
●
The generic counterpart of the collection ArrayList is List<T>, T is the type parameter.
– List<T>'s interface is set to the open type T in parameter- and return-types of methods.
– The type parameter T acts as a placeholder for the actual type argument.
●
When a type is constructed, T is replaced by a type argument (the result is the constructed type).
– List<string>'s interface is set to the static type string in parameter- and return- types of methods.
●
The idea of generics is to use types (i.e. not values) as arguments!
– The typesafty we got is that generics move type run time errors to compile time errors.
// The generic type List<T>:
public class List<T> { // (details hidden)
public void Add(T item) { /* pass */ }
public List<T> GetRange(int index, int count) { /* pass */ }
}
// The constructed type List<string> has following interface:
public class List<string> { // (details hidden)
public void Add(string item) { /* pass */ }
public List<string> GetRange(int index, int count) { /* pass */ }
}
// Create a generic List that holds strings:
List<string> lines;
List
T
The UML represents generic
types as parameterized classes.
Generics – Overview
List<T -> string>
«bind»
<T -> string>
List<string>
implicit binding against a type
argument
explicit binding against a type
argument
10
10
●
It is also possible to define generic types, whose type argument is another generic type.
– E.g. we can define a list of lists, i.e. a collection of collections, which is effectively a two-dimensional array or matrix.
– Such collections are better than multidimensional arrays in some aspects:
●
They offer the same concept to express rectangular as well as jagged arrays.
●
"Real" collections are very flexible, as elements can be added and removed (or: the matrix' dimensions can be enlarged and shrank).
●
The .Net framework as well as Java do also support generic types having two or more type parameters:
– E.g. with the type SortedDictionary<TKey, Tvalue> (this type will be discussed later):
●
To understand collections in Java, C++ and .Net it is required to understand alsoadvanced generics.
// Creating a SortedDictionary object:
SortedDictionary<string, int> aDictionary = new SortedDictionary<string, int>();
aDictionary.Add("fortytwo", 42);
// The generic type SortedDictionary<TKey, TValue>:
public class SortedDictionary<TKey, TValue> { // (members hidden)
/* pass */
}
// A jagged array in C# as matrix:
int[][] matrix = new int[3][];
matrix[0] = new[] {1, 2, 3, 4};
matrix[1] = new[] {6, 7};
matrix[2] = new[] {8, 9, 0};
Console.WriteLine("Item: {0}", matrix[1][0]);
// >Item: 6
// A list of lists of int as matrix:
List<List<int>> matrix = new List<List<int>>();
matrix.Add(new List<int>{1, 2, 3, 4});
matrix.Add(new List<int>{6, 7});
matrix.Add(new List<int>{8, 9, 0});
Console.WriteLine("Item: {0}", matrix[1][0]);
// >Item: 6
Slightly advanced Generics
11
11
●
Hence, we'll use generic types whenever appropriate. We'll define following substitutes for already introduced collections:
– ICollection → ICollection<T>
– IList → IList<T>
– ArrayList → List<T>
– IEnumerable → IEnumerable<T>
– IEnumerator → IEnumerator<T>
– .Net's framework design guidelines suggest using only generic collection types in public interfaces.
●
From object-based to generic collections:
IList names = new ArrayList();
names.Add("James");
names.Add("Miranda");
// Get the values back (object-based collection: static type Object):
object name1 = names[0]; // "James"
object name2 = names[1]; // "Miranda"
string name1AsString = (string)name1; // Cast the string out of the object.
string name2As = (string)names[1]; // Cast directly from the index notation.
names[1] = "Meredith";
Console.WriteLine(names[1]);
// >Meredith
IList<string> names = new List<string>();
names.Add("James");
names.Add("Miranda");
// Get the values back (generic string-collection: static type string):
string name1 = names[0]; // "James"
string name2 = names[1]; // "Miranda"
names[1] = "Meredith";
Console.WriteLine(names[1]);
// >Meredith
The better Type System –
from object-based to generic Collections
12
12
●
C++ templates are, at least principally, C++' equivalent to .Net's and Java's generics.
– C++ provides the template std::vector<T> (<vector>), which is functionally equivalent to .Net's List<T>:
– Before C++ had templates, void*-based collections have been used, incl. cast contact lenses. - This is still true for C.
●
void*-based collections are the functional equivalent to object-based collections!
●
Objective-C and many scripting languages use so calleddynamic typing instead of generic or object-based structures.
– (We're not going to discuss these concepts in this course.)
// names is a vector containing string-elements.
std::vector<std::string> names;
names.push_back("James");
names.push_back("Miranda");
// Get the values back (template string-container: static type std::string):
std::string name1 = names[0]; // "James"
std::string name2 = names[1]; // "Miranda"
names[1] = "Meredith";
std::cout<<names[1]<<std::endl;
// >Meredith
// in h-file <vector>
template <typename T> class vector { // (details hidden)
public:
void push_back(const T& newItem);
};
The Collection Type System of the C++ STL
13
13
●
The story about generic collections in Java is somewhat advanced,but Java programmers should know these facts.
– A good way to understand Java's generics (and the problems that come with it) is to compare them to, e.g., .Net's generics.
●
Here we have basically the same generic class in Java and C#:
– The definition of instances of these classes has almost the same syntax in Java and C#:
●
In Java we can only use reference types as type arguments for generic types. E.g. we can not create MyList<int> or MyList<double>.
– As we know the idea behind generics is to have typesafty. So the last statements won't compile respectively:
The Collection Type System on the Java Platform – Part I
// Java
public class MyList<T> {
public List<T> items = new ArrayList<T>(5);
}
// Java
stringList.items.add("Frank"); // OK for the compiler! A string literal can be set, because items is a List<String>.
stringList.items.add(42); // Invalid for the compiler! Generics are typesafe! An int literal can't be set, because items is not a List<Integer>.
MyList<String> stringList = new MyList<String>();
MyList<Integer> intList = new MyList<Integer>();
MyList<string> stringList = new MyList<string>();
MyList<int> intList = new MyList<int>();
// C#
public class MyList<T> {
public IList<T> items = new List<T>(5);
}
// C#
stringList.items.Add("Frank"); // OK for the compiler! See explanation for Java above.
stringList.items.Add(42); // Invalid for the compiler! See explanation for Java above.
14
14
●
The difference between Java and .Net is that different things are generated at compile time.
– A compiler creating .Net IL code will produce a so called constructed type for each "filled out" generic type in the code:
– A compiler creating Java bytecode will just erase the type argument and will fall back to an object-based type:
●
This compilation step is called type erasure. The resulting type (w/o generic type parameters) is called the raw type of the generic type.
●
Often this isn't a problem in Java, because compile time typesafety is fine, but it hurts the run time typesafety!
●
Ouch! But Java provides a means to reestablish run time typesafety: run time type checked collection wrappers.
The Collection Type System on the Java Platform – Part II
stringList.items.add("Frank"); // Ok as before!
((MyList)stringList).items.add(42); // Huh? Casting (cast contact lenses) to the raw type and adding an int: ok for compiler and at run time!
String itemAt1 = stringList.items.get(1); // Bang! Getting the int at the index one via the generic type: ok for the compiler but crashes at run time!
// java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
type construction of a .Net IL compiler
// Java
MyList<String> stringList = new MyList<String>();
MyList<Integer> intList = new MyList<Integer>();
public class MyList { // Raw type
public List items = new ArrayList(5);
}
type erasure of a Java bytecode compiler
// C#
MyList<string> stringList = new MyList<string>();
MyList<int> intList = new MyList<int>();
public class MyList<string> { // Constructed type
public IList<string> items = new List<string>(5);
}
public class MyList<int> { // Constructed type
public IList<int> items = new List<int>(5);
}
15
15
●
Java provides the class Collections with some static methods (simple factories) to create run time type checked collections.
– A present collection needs to be passed to Collections.checked...() and a new collection wrapping the passed one will be returned.
– Let's wrap MyList's encapsulated List to be a checked List with Collections.checkedList():
●
More simple factories can be found in the class Collections as static methods (checkedSet(), checkedMap() etc.).
– The return type of all of these simple factories are just interface types, the type checked implementations are always hidden.
– So the UML diagram of the relations between the contributing types looks like so:
●
Run time type checked wrappers were added to the JDK in order have compatibility w/ non-generic collections, retaining
compile time typesafty of generics and having run time typesafety.
– There is an initiative in the Java community to introduce generic types with constructed types into Java: reified generics.
– Mind that run time type checking is costly!
The Collection Type System on the Java Platform – Part III
stringList.items = Collections.checkedList(stringList.items, String.class); // Wrap items, so that it can only deal with strings at compile time.
stringList.items.add("Frank"); // Ok as before! It was already checked by the compiler.
((MyList)stringList).items.add(42); // Bang! An int can't be added to a list that is only allowed to contain Strings!
String itemAt1 = stringList.items.get(1); // Will not be reached at all!
<<interface>>
List
HiddenCheckedListImplementation
exposes implements
Collections
+ checkedList(list : List<T>, type : Class<T>) : List<T>
instantiates
T
16
16
●
Up to now, we discussed relatively simple indexed and sequential collections.
●
Besides indexed and sequential collections there also exist so calledassociative collections.
●
In opposite to indexed and sequential collections,associative collections inspect the stored objects.
– E.g. the indexed collection ArrayList just stores references to objects, but it does never, e.g., call methods on these objects.
●
For indexed and sequential collections the contained items are said to be transparent.
– Associative collections have to inspect stored objects for equivalence or equality in order to provide very mighty features.
●
Let's start by analyzing a problem, which can be solved with associative collections.
Indexed, sequential and associative Collections
17
17
●
Let's assume that we have to handle color names and figure out the belonging to HTML color codes:
●
Of course the task can be solved this way, but the solution is based on a possiblyfragile assumption:
– The two separate arrays need to hold belonging to values at the same indexes!
– Basically we've to go through all items sequentially and compare (Array.IndexOf()).
– We say the association is index-based.
●
The presented algorithm is a so called lookup-algorithm (lookup).
– Lookups are used very often in programming.
– A problem of lookups is that separate collections (colorNames and htmlColorCode) need to be evaluated (like tables in relational databases).
– Modern collection frameworks provide dedicated collections to cover lookups in a comfortable manner: associative collections.
// C#
// Here we have two arrays that hold color names and HTML color codes:
string[] colorNames = {"Blue", "Red", "Green"} ;
int[] htmlColorCodes = {0x0000FF, 0xFF0000, 0x00FF00};
// With the information given, the task to pick an HTML color code from a color name is trivial: Because the
// index of the color name matches the index of the color HTML code, we can formulate a simple algorithm:
int indexOfRed = Array.IndexOf(colorNames, "Red");
int colorCodeOfRed = htmlColorCodes[indexOfRed];
Console.WriteLine("Color code for Red: {0:X6}", colorCodeOfRed);
// >Color code for Red: FF0000
colorNames0x0000FF 0xFF0000 0x00FF00
"Blue" "Red" "Green" htmlColorCodes
210 matching indexes
Example – Color Names to HTML Color Codes – Part I
18
18
colorNamesToColorCodes
●
Associative collections abstract the usage of multiple collections to solve the just presented lookupin an intuitive manner:
– Here .Net's associative collection SortedDictionary<string, int> is shown (it implements IDictionary<string, int>):
– The association of both, color names and color codes, is available via the single collection colorNamesToHtmlColorCodes.
●
We have to rethink our termination: associative collections associate a key (color name) to a value (color code).
– The association is key-based and no longer index-based.
– The internal "organization" is key-value-pair-based.
– In a sense an array is nothing but an associative collection that associates a value with an index (mind the []-syntax).
– In fact real problems often involve associating values with other values, e.g.: White pages, thesaurus, document index.
●
The .Net collection KeyedCollection<K, T> allows the lookup of data stored in the value (i.e. there are no key-value-pairs).
// Associating color names with HTML color codes using a SortedDictionary:
IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>();
colorNamesToColorCodes.Add("Blue", 0x0000FF);
colorNamesToColorCodes.Add("Red", 0xFF0000);
colorNamesToColorCodes.Add("Green", 0x00FF00);
int colorCodeOfRed = colorNamesToColorCodes["Red"];
Console.WriteLine("Color code for Red: {0:X6}", colorCodeOfRed);
// >Color code for Red: FF0000
0x0000FF 0xFF0000 0x00FF00
"Blue" "Red" "Green"
Key-value-pair
{"Green", 0x00FF00}
Example – Color Names to HTML Color Codes – Part II
● Mind how the term key (primary/foreign key) is also
applied in the design of databases.
● Indeed KeyedCollection is a very useful collection.
However, it is not a classical associative collection,
because it uses linear search (it is backed by a List
and calls Contains() on that List potentially for each
item). The abstract class KeyedCollection needs to
be specialized (overriding GetKeyForItem(), i.e. we
have the template method design pattern here) to
get the key from the managed item/value.
19
19
●
In many scripting languages associative collections havespecial syntactical support.
– The names "hash", "hashmap" or "associative array" are common in scripting languages.
– In JavaScript every object is a collection of property-value-pairs per se. An array is also an associative collection:
●
In other platforms associative collections are often called Maps (Java) or Dictionaries (Cocoa, .Net).
– Esp. the term "Map" is taken from the phrase "to map something", which means "to associate something".
– The term "hash" still needs to be clarified in this context: we have to understand how associative collections work.
●
We'll start discussing equivalence-based associative collections and then equality-based associative collections using hashing.
# E.g. in Ruby associative collections are supported as "hashes" with integrated syntactical support.
# Just initialize a variable with a list of key => value pairs:
colorNamesToColorCodes = {"Blue" => 0x0000FF, "Red" => 0xFF0000, "Green" => 0x00FF00}
# The items can be accessed with the []-operator:
printf("Color code for Red: %06X", colorNamesToColorCodes["Red"])
# >Color code for Red: FF0000
// JavaScript
// Create associative collection as object with properties:
var colorNamesToColorCodes = new Object();
colorNamesToColorCodes.Blue = 0x0000FF;
colorNamesToColorCodes.Red = 0xFF0000;
colorNamesToColorCodes.Green = 0x00FF00;
console.log("Color code for Red: "
+colorNamesToColorCodes.Red.toString(16));
// >Color code for Red: FF0000
// JavaScript
// Create associative collection as associative array:
var colorNamesToColorCodes = new Object();
colorNamesToColorCodes["Blue"] = 0x0000FF;
colorNamesToColorCodes["Red"]= 0xFF0000;
colorNamesToColorCodes["Green"]= 0x00FF00;
console.log("Color code for Red: "
+colorNamesToColorCodes["Red"].toString(16));
// >Color code for Red: FF0000
Associative Collections in other Languages
20
20
●
New about associative collections is that associative collections inspect the items they hold.
– I.e. associative collections operate on contained items: they call methods on the keys of the contained key-value-pairs.
– Associative collections need to compare the keys they hold.
– In opposite to other collections, items are got and set by analyzing their relationships.
●
Associative collections are very powerful and allow writing elegant/readable algorithms to solve complicated problems.
– Associative collections could be implemented with two arrays as shown before, but this would be inefficient for common cases.
– A clever internal organization of associative collections is required to allow efficient access and modification of contained items.
●
There are two general ways to organize items (i.e. their keys) in an associative collection:
– (1) By equivalence. I.e. by their relative order/order-relationship, such as less than and greater than.
– (2) By equality. I.e. by hash-codes and the result of the equality check (methods hashCode()/equals() (Java) or
GetHashCode()/Equals() (.Net)).
●
In this and the next lecture we're going to discuss associative collections that organize their keys byequivalence.
– This is the case for SortedDictionary, so we'll discuss .Net's SortedDictionary.
Organization of Items in associative Collections
● It should be mentioned that some methods of list-
types already needed to inspect the contained items
to function, e.g. Contains(), Remove(), IndexOf().
These methods use equality to inspect/compare
values.
21
21
●
Create the empty SortedDictionary<K, V> colorNamesToColorCodes:
●
Then we can add three key-value-pairs like so:
●
Get the value of a key, i.e. make a lookup with the indexer ([]-operator):
●
Check, whether an entry with a certain key is already existing with the method ContainsKey():
●
Iteration: The internal organization is key-value-pair-based, so IDictionary's iterator produces an iterator of key-value pairs.
C# – collection initializers for dictionaries
// Apply a collection initializer on a SortedDictionary:
IDictionary<string, int> colorNamesToColorCodes2 = new SortedDictionary<string, int> {
{"Blue", 0x0000FF}, {"Red", 0xFF0000}, {"Green", 0x00FF00}
};
IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>();
colorNamesToColorCodes.Add("Blue", 0x0000FF);
colorNamesToColorCodes.Add("Red", 0xFF0000);
colorNamesToColorCodes.Add("Green", 0x00FF00);
int valueForBlue = colorNamesToColorCodes2["Blue"];
// >0x0000FF
Operations on IDictionarys – Part I
// IDictionary<string, int> implements IEnumerable<KeyValuePair<string, int>>.
// Iteration yields KeyValuePair<string, int>-items:
foreach (KeyValuePair<string, int> item in colorNamesToColorCodes) {
Console.WriteLine(item);
}
bool blueAlreadyPresent = colorNamesToColorCodes2.ContainsKey("Blue");
// >true
● Because colorNamesToColorCodes is virtually a
SortedDictionary, the iteration will yield the items in
the order sorted by their keys.
22
22
●
Trying to query the value for a key that doesn't exist will throw a KeyNotFoundException:
– To avoid these "surprises" check the key for existence (with ContainsKey()), before it is looked up.
●
Adding a pair for an already existing key will throw an ArgumentException.
– .Net dictionaries don't allow having a key with multiple values. (However, the C++' STL-container std::multimap can handle this.)
●
The indexer allows adding new entries as well as replacing values of existing key-value-pairsand reading values:
●
We can get the current count of elements stored in the dictionary (Count is required by implementing ICollection<T>):
colorNamesToColorCodes.Add("Blue", 17); // Throws ArgumentException: a key-value-pair with the same key already exists in the dictionary.
colorNamesToColorCodes["Blue"] = 17; // OK! Replaces "Blue"'s value 0x0000FF with 17.
colorNamesToColorCodes["Yellow"] = 0xFFFF00; // Adds the new key-value-pair {"Yellow", 0xFFFF00}.
if (colorNamesToColorCodes.ContainsKey("Yellow")) { // Checking the existence of the key "Yellow".
// Use the indexer to retrieve "Yellow"'s value:
Console.WriteLine("Color code for Yellow: {0:X6}", colorNamesToColorCodes["Yellow"]);
// >Color code for Yellow: FFFF00
}
Console.WriteLine(colorNamesToColorCodes.Count);
// >4
Operations on IDictionarys – Part II
int valueForOrange = colorNamesToColorCodes2["Orange"]; // Throws KeyNotFoundException: a key-value-pair with that key doesn't exists in the dictionary.
23
23
●
Now its time to understand how SortedDictionarys work basically, we'll discuss it in depth in the next lecture.
– We have to clarify, how SortedDictionary knows if a key is already present or not! - It needs to compare keys somehow!
●
The question is: "How does SortedDictionary know if two keys are equal?"
– A part of the answer is that SortedDictionary doesn't know, if two items are equal, but it knows if two items are equivalent!
– SortedDictionary's comparison is based on the order-relationship among items. This is called equivalence comparison.
●
The order-relationship can be expressed by evaluating two values one beingless than, greater than or equal the other.
– If of two values one is neither less than nor greater than the other the values are said to be equivalent (Not equal!).
– .Net provides a way for types to declare equivalence comparability: implementing the interface IComparable/IComparable<T>.
– (The C++ STL requires types to override operator< to implement equivalence comparability.)
●
Now we are going to understand how IComparable/IComparable<T> has to be implemented for own UDTs.
SortedDictionary and Equivalence Comparison
24
24
UDTs as Keys of associative Collections – Part I
● Up to now we've only used objects of builtin types for the keys of associative collections (e.g. string).
– Now we are going to explore how to use keys of our own types. Let's do this with the UDT Car:
– Obviously it doesn't work this way! - What did we miss?
● The problem is that nobody (esp. SortedDictionary) knows, how to compare Cars!
– One way to implement this: Car could itself know, how it can be compared – we've to implement IComparable<Car> in Car:
– IComparable<T>.CompareTo() should return a value less than 0, if this < other, a value greater than 0, if this > other and otherwise 0.
●
For Car we'll delegate the implementation of
IComparable<Car>.CompareTo() to Car's property
Name, Name is of type string (string implements
IComparable<string>).
– With this implementation of Car
SortedDictionary<TKey, TValue> works
as expected:
public class Car {
public string Name {get; set;}
}
IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>();
// Adding the first item won't require to compare items:
carToManufacturer[new Car{ Name = "Focus" }] = "Ford";
// Will throw ArgumentException: Object doesn't implement IComparable!
carToManufacturer[new Car{ Name = "Auris" }] = "Toyota";
IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>();
carToManufacturer[new Car{ Name = "Focus" }] = "Ford";
// OK!
carToManufacturer[new Car{ Name = "Auris" }] = "Toyota";
public class Car : IComparable<Car> { // (members hidden)
public int CompareTo(Car other) {
// Very simple implementation that compares the Cars' Name fields:
return this.Name.CompareTo(other.Name);
}
}
● The associative collection does really look into the
items: just set a breakpoint into the Car.
CompareTo() method!
25
25
UDTs as Keys of associative Collections – Part II
● But there are cases, in which implementing IComparable<T> is no option to make types usable as keys:
– (1) if we can not modify the type in question, e.g. if it is a type of a 3rd
party library,
– (2) if the type in question does already implement IComparable<T>, but the implemented comparison doesn't meet our needs,
– (3) if the type doesn't implement IComparable<T> at all.
● Let's assume that we want to use Cars as keys by case insensitive comparison of their Name property.
– We could change the implementation of Car.CompareTo(), but this would hurt the Open-Close Principle (OCP).
– Effectively we have the case (2). The present implementation of IComparable<Car> doesn't meet our needs.
● To cover these cases there is another way to implement comparison:implement comparison in a different type (not in Car).
– I.e. we can implement a dedicated type that has only one responsibility: comparing Cars. Such a type is called comparator.
– The .Net framework provides a special interface to support such special comparison types: IComparer/IComparer<T>.
– Now it's time to implement a comparer to compare the case insensitive Name of Cars.
● If a type does not implement IComparable<T>, and
we try to add at least two instances of that type used
as key into a SortedDictionary, an
ArgumentException will be thrown.
26
26
UDTs as Keys of associative Collections – Part III
● The type SortedDictionary<TKey, TValue> accepts an object of type IComparer<TKey> in one of its ctors:
– As can be seen the passed comparer refers to the type TKey.
● The comparer to specify in the ctor determines, how Cars are getting compared. The comparer looks like this:
● Here we'll finally pass an instance of the created CaseInsensitveCarComparer to SortedDictionary's ctor:
public class CaseInsensitiveCarComparer : IComparer<Car> {
public int Compare(Car lhs, Car rhs) {
// Very simple implementation that compares the Name
// fields of two Cars ignoring the case:
return string.Compare(lhs.Name, rhs.Name, true);
}
}
// The generic type SortedDictionary<TKey, TValue>:
public class SortedDictionary<TKey, TValue> { // (details hidden)
public SortedDictionary(IComparer<TKey> comparer);
}
// Create a dictionary and specify the special comparer in the ctor:
IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>(new CaseInsensitiveCarComparer());
carToManufacturer[new Car{ Name = "Cortina" }] = "Ford";
// This won't add another "cortina", because the specified comparer evaluates "Cortina" and "cortina" as being equivalent.
carToManufacturer[new Car{ Name = "cortina" }] = "Lotus"; // Will set "Cortina"'s value to "Lotus".
Console.WriteLine("Count of items: {0}", carToManufacturer.Count);
// >Count of items: 1
27
27
Controlling String-Key Comparison
● If we use strings as keys (i.e. not a UDT like Car), we can use predefined comparers to compare case insensitively.
– The .Net framework provides a set of predefined StringComparer objects in the type StringComparer.
– Let's rewrite the color code example for case insensitive color names:
– We can do the same with Java's TreeMap managing string-keys case-insensitively using a special Comparator:
– If we like to exploit the sorting of the Map and want the keys to be sorted in descending order, just reverse the Comparator:
// Create a dictionary and specify the case insensitive string comparer in the ctor:
IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>(StringComparer.OrdinalIgnoreCase);
colorNamesToColorCodes.Add("Green", 0x00FF00);
// Because of the case insensitive comparison "Green" and "green" are seen as equivalent key objects:
int colorCodeOfGreen = colorNamesToColorCodes["green"];
Console.WriteLine("Color code for Green: {0:X6}", colorCodeOfGreen);
// >Color code for Green: 00FF00
// Create a map and specify the case insensitive string comparator in the ctor:
Map<String, Integer> colorNamesToColorCodes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
colorNamesToColorCodes.put("Green", 0x00FF00);
// Because of the case insensitive comparison "Green" and "green" are seen as equivalent key objects:
int colorCodeOfGreen = colorNamesToColorCodes.get("green");
System.out.printf("Color code for Green: %06X%n", colorCodeOfGreen);
// >Color code for Green: 00FF00
// Create a map and specify the case insensitive string comparator in the ctor, the sorting should be descending:
Map<String, Integer> colorNamesToColorCodesDescending =
new TreeMap<>(Collections.reverseOrder(String.CASE_INSENSITIVE_ORDER));
● Creating a reversed Comparer by passing an
existing Comparer to Collections.reverseOrder() is
an example of the decorator pattern. A present
Comparer is decorated with extra functionality and
the new object has the same interface than the one
being decorated.
28
28
Thank you!

More Related Content

What's hot

Quick Scala
Quick ScalaQuick Scala
Quick Scala
Puneet Kumar
 
C++ - Constructors,Destructors, Operator overloading and Type conversion
C++ - Constructors,Destructors, Operator overloading and Type conversionC++ - Constructors,Destructors, Operator overloading and Type conversion
C++ - Constructors,Destructors, Operator overloading and Type conversion
Hashni T
 
Learning core java
Learning core javaLearning core java
Learning core java
Abhay Bharti
 
#_ varible function
#_ varible function #_ varible function
#_ varible function
abdullah al mahamud rosi
 
String & path functions in vba
String & path functions in vbaString & path functions in vba
String & path functions in vba
gondwe Ben
 
Variable
VariableVariable
Java core - Detailed Overview
Java  core - Detailed OverviewJava  core - Detailed Overview
Java core - Detailed Overview
Buddha Tree
 
5variables in c#
5variables in c#5variables in c#
5variables in c#
Sireesh K
 
Java scanner, everything you need to know about Java Scanner
Java scanner, everything you need to know about Java ScannerJava scanner, everything you need to know about Java Scanner
Java scanner, everything you need to know about Java Scanner
Edward Nyang'ali
 
C,s&s
C,s&sC,s&s
C,s&s
sid6376
 
Core Java Basics
Core Java BasicsCore Java Basics
Core Java Basics
mhtspvtltd
 
Comparable/ Comparator
Comparable/ ComparatorComparable/ Comparator
Comparable/ Comparator
Sean McElrath
 
Introduction to TypeScript
Introduction to TypeScriptIntroduction to TypeScript
Introduction to TypeScript
KeithMurgic
 
Introduction To C#
Introduction To C#Introduction To C#
Introduction To C#
SAMIR BHOGAYTA
 
Actors model in gpars
Actors model in gparsActors model in gpars
Actors model in gpars
NexThoughts Technologies
 
StringTokenizer in java
StringTokenizer in javaStringTokenizer in java
StringTokenizer in java
Muthukumaran Subramanian
 
M C6java2
M C6java2M C6java2
M C6java2
mbruggen
 
Jdk1.5 Features
Jdk1.5 FeaturesJdk1.5 Features
Jdk1.5 Features
india_mani
 
M C6java7
M C6java7M C6java7
M C6java7
mbruggen
 
C# basics
 C# basics C# basics
C# basics
Dinesh kumar
 

What's hot (20)

Quick Scala
Quick ScalaQuick Scala
Quick Scala
 
C++ - Constructors,Destructors, Operator overloading and Type conversion
C++ - Constructors,Destructors, Operator overloading and Type conversionC++ - Constructors,Destructors, Operator overloading and Type conversion
C++ - Constructors,Destructors, Operator overloading and Type conversion
 
Learning core java
Learning core javaLearning core java
Learning core java
 
#_ varible function
#_ varible function #_ varible function
#_ varible function
 
String & path functions in vba
String & path functions in vbaString & path functions in vba
String & path functions in vba
 
Variable
VariableVariable
Variable
 
Java core - Detailed Overview
Java  core - Detailed OverviewJava  core - Detailed Overview
Java core - Detailed Overview
 
5variables in c#
5variables in c#5variables in c#
5variables in c#
 
Java scanner, everything you need to know about Java Scanner
Java scanner, everything you need to know about Java ScannerJava scanner, everything you need to know about Java Scanner
Java scanner, everything you need to know about Java Scanner
 
C,s&s
C,s&sC,s&s
C,s&s
 
Core Java Basics
Core Java BasicsCore Java Basics
Core Java Basics
 
Comparable/ Comparator
Comparable/ ComparatorComparable/ Comparator
Comparable/ Comparator
 
Introduction to TypeScript
Introduction to TypeScriptIntroduction to TypeScript
Introduction to TypeScript
 
Introduction To C#
Introduction To C#Introduction To C#
Introduction To C#
 
Actors model in gpars
Actors model in gparsActors model in gpars
Actors model in gpars
 
StringTokenizer in java
StringTokenizer in javaStringTokenizer in java
StringTokenizer in java
 
M C6java2
M C6java2M C6java2
M C6java2
 
Jdk1.5 Features
Jdk1.5 FeaturesJdk1.5 Features
Jdk1.5 Features
 
M C6java7
M C6java7M C6java7
M C6java7
 
C# basics
 C# basics C# basics
C# basics
 

Viewers also liked

Asturias la belleza
Asturias la bellezaAsturias la belleza
Asturias la belleza
supermediania
 
Educar para proteger
Educar para protegerEducar para proteger
Educar para proteger
guadalinfocazalilla
 
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake RecommendationEl Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
epdevelopment
 
Greening Your School Bus for Administrators Webinar
Greening Your School Bus for Administrators WebinarGreening Your School Bus for Administrators Webinar
Greening Your School Bus for Administrators Webinar
Wisconsin Clean Cities
 
Science collection
Science collectionScience collection
Science collection
Alejandra Diaz
 

Viewers also liked (7)

Asturias la belleza
Asturias la bellezaAsturias la belleza
Asturias la belleza
 
max planc
max plancmax planc
max planc
 
กระบวนการโครงงาน
กระบวนการโครงงานกระบวนการโครงงาน
กระบวนการโครงงาน
 
Educar para proteger
Educar para protegerEducar para proteger
Educar para proteger
 
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake RecommendationEl Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
El Paso City Council 09.09.14 Agenda Item 15.2: Osab Cement Lake Recommendation
 
Greening Your School Bus for Administrators Webinar
Greening Your School Bus for Administrators WebinarGreening Your School Bus for Administrators Webinar
Greening Your School Bus for Administrators Webinar
 
Science collection
Science collectionScience collection
Science collection
 

Similar to (4) collections algorithms

Typescript: Beginner to Advanced
Typescript: Beginner to AdvancedTypescript: Beginner to Advanced
Typescript: Beginner to Advanced
Talentica Software
 
ActionScript 3.0 Fundamentals
ActionScript 3.0 FundamentalsActionScript 3.0 Fundamentals
ActionScript 3.0 Fundamentals
Saurabh Narula
 
Type system
Type systemType system
Chapter 1 Presentation
Chapter 1 PresentationChapter 1 Presentation
Chapter 1 Presentation
guest0d6229
 
Java Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and PitfallsJava Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and Pitfalls
Rakesh Waghela
 
(2) collections algorithms
(2) collections algorithms(2) collections algorithms
(2) collections algorithms
Nico Ludwig
 
(6) collections algorithms
(6) collections algorithms(6) collections algorithms
(6) collections algorithms
Nico Ludwig
 
I x scripting
I x scriptingI x scripting
I x scripting
Alex do Amaral Dias
 
Effective Java Second Edition
Effective Java Second EditionEffective Java Second Edition
Effective Java Second Edition
losalamos
 
Java New Programming Features
Java New Programming FeaturesJava New Programming Features
Java New Programming Features
tarun308
 
typescript.pptx
typescript.pptxtypescript.pptx
typescript.pptx
ZeynepOtu
 
Beginning linq
Beginning linqBeginning linq
Beginning linq
Shikha Gupta
 
(2) collections algorithms
(2) collections algorithms(2) collections algorithms
(2) collections algorithms
Nico Ludwig
 
(6) collections algorithms
(6) collections algorithms(6) collections algorithms
(6) collections algorithms
Nico Ludwig
 
venkatesh.pptx
venkatesh.pptxvenkatesh.pptx
venkatesh.pptx
KishoreRedla
 
Notes(1).pptx
Notes(1).pptxNotes(1).pptx
Notes(1).pptx
InfinityWorld3
 
C++ Standard Template Library
C++ Standard Template LibraryC++ Standard Template Library
C++ Standard Template Library
Ilio Catallo
 
(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings
Nico Ludwig
 
Python internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvandPython internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvand
irpycon
 
C Types - Extending Python
C Types - Extending PythonC Types - Extending Python
C Types - Extending Python
Priyank Kapadia
 

Similar to (4) collections algorithms (20)

Typescript: Beginner to Advanced
Typescript: Beginner to AdvancedTypescript: Beginner to Advanced
Typescript: Beginner to Advanced
 
ActionScript 3.0 Fundamentals
ActionScript 3.0 FundamentalsActionScript 3.0 Fundamentals
ActionScript 3.0 Fundamentals
 
Type system
Type systemType system
Type system
 
Chapter 1 Presentation
Chapter 1 PresentationChapter 1 Presentation
Chapter 1 Presentation
 
Java Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and PitfallsJava Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and Pitfalls
 
(2) collections algorithms
(2) collections algorithms(2) collections algorithms
(2) collections algorithms
 
(6) collections algorithms
(6) collections algorithms(6) collections algorithms
(6) collections algorithms
 
I x scripting
I x scriptingI x scripting
I x scripting
 
Effective Java Second Edition
Effective Java Second EditionEffective Java Second Edition
Effective Java Second Edition
 
Java New Programming Features
Java New Programming FeaturesJava New Programming Features
Java New Programming Features
 
typescript.pptx
typescript.pptxtypescript.pptx
typescript.pptx
 
Beginning linq
Beginning linqBeginning linq
Beginning linq
 
(2) collections algorithms
(2) collections algorithms(2) collections algorithms
(2) collections algorithms
 
(6) collections algorithms
(6) collections algorithms(6) collections algorithms
(6) collections algorithms
 
venkatesh.pptx
venkatesh.pptxvenkatesh.pptx
venkatesh.pptx
 
Notes(1).pptx
Notes(1).pptxNotes(1).pptx
Notes(1).pptx
 
C++ Standard Template Library
C++ Standard Template LibraryC++ Standard Template Library
C++ Standard Template Library
 
(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings
 
Python internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvandPython internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvand
 
C Types - Extending Python
C Types - Extending PythonC Types - Extending Python
C Types - Extending Python
 

More from Nico Ludwig

Grundkurs fuer excel_part_v
Grundkurs fuer excel_part_vGrundkurs fuer excel_part_v
Grundkurs fuer excel_part_v
Nico Ludwig
 
Grundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivGrundkurs fuer excel_part_iv
Grundkurs fuer excel_part_iv
Nico Ludwig
 
Grundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiGrundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iii
Nico Ludwig
 
Grundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiGrundkurs fuer excel_part_ii
Grundkurs fuer excel_part_ii
Nico Ludwig
 
Grundkurs fuer excel_part_i
Grundkurs fuer excel_part_iGrundkurs fuer excel_part_i
Grundkurs fuer excel_part_i
Nico Ludwig
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
Nico Ludwig
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
Nico Ludwig
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
Nico Ludwig
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
Nico Ludwig
 
New c sharp4_features_part_vi
New c sharp4_features_part_viNew c sharp4_features_part_vi
New c sharp4_features_part_vi
Nico Ludwig
 
New c sharp4_features_part_v
New c sharp4_features_part_vNew c sharp4_features_part_v
New c sharp4_features_part_v
Nico Ludwig
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_iv
Nico Ludwig
 
New c sharp4_features_part_iii
New c sharp4_features_part_iiiNew c sharp4_features_part_iii
New c sharp4_features_part_iii
Nico Ludwig
 
New c sharp4_features_part_ii
New c sharp4_features_part_iiNew c sharp4_features_part_ii
New c sharp4_features_part_ii
Nico Ludwig
 
New c sharp4_features_part_i
New c sharp4_features_part_iNew c sharp4_features_part_i
New c sharp4_features_part_i
Nico Ludwig
 
New c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNew c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_v
Nico Ludwig
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
New c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNew c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iii
Nico Ludwig
 
New c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNew c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_ii
Nico Ludwig
 

More from Nico Ludwig (20)

Grundkurs fuer excel_part_v
Grundkurs fuer excel_part_vGrundkurs fuer excel_part_v
Grundkurs fuer excel_part_v
 
Grundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivGrundkurs fuer excel_part_iv
Grundkurs fuer excel_part_iv
 
Grundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiGrundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iii
 
Grundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiGrundkurs fuer excel_part_ii
Grundkurs fuer excel_part_ii
 
Grundkurs fuer excel_part_i
Grundkurs fuer excel_part_iGrundkurs fuer excel_part_i
Grundkurs fuer excel_part_i
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
New c sharp4_features_part_vi
New c sharp4_features_part_viNew c sharp4_features_part_vi
New c sharp4_features_part_vi
 
New c sharp4_features_part_v
New c sharp4_features_part_vNew c sharp4_features_part_v
New c sharp4_features_part_v
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_iv
 
New c sharp4_features_part_iii
New c sharp4_features_part_iiiNew c sharp4_features_part_iii
New c sharp4_features_part_iii
 
New c sharp4_features_part_ii
New c sharp4_features_part_iiNew c sharp4_features_part_ii
New c sharp4_features_part_ii
 
New c sharp4_features_part_i
New c sharp4_features_part_iNew c sharp4_features_part_i
New c sharp4_features_part_i
 
New c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNew c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_v
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNew c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iii
 
New c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNew c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_ii
 

Recently uploaded

Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
ScyllaDB
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
Ortus Solutions, Corp
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
Enterprise Knowledge
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
Fwdays
 
Containers & AI - Beauty and the Beast!?!
Containers & AI - Beauty and the Beast!?!Containers & AI - Beauty and the Beast!?!
Containers & AI - Beauty and the Beast!?!
Tobias Schneck
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Neo4j
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
Sease
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
Safe Software
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
ScyllaDB
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
Ajin Abraham
 
The Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptxThe Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptx
operationspcvita
 
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Ukraine
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
UiPathCommunity
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
HarpalGohil4
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
DianaGray10
 

Recently uploaded (20)

Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
 
Containers & AI - Beauty and the Beast!?!
Containers & AI - Beauty and the Beast!?!Containers & AI - Beauty and the Beast!?!
Containers & AI - Beauty and the Beast!?!
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
 
The Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptxThe Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptx
 
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
 

(4) collections algorithms

  • 2. 2 2 ● Collections – Part IV – Object-based vs. generic Collections ● Generics Types in Java – Sequential and associative Collections – Associative Collections ● Equivalence-based associative Collections: .Net's SortedDictionary ● Operations on .Net's IDictionarys ● Comparison and Implementation of .Net's Interfaces IComparable and IComparer TOC
  • 3. 3 3 ● Explicitly typed – i.e. typenames must be explicitly written at their declaration: ● Safely typed – i.e. unrelated types can't fool the compiler. – Cross casting and other pointer stuff is generally illegal. ● Statically typed – i.e. variables' types are determined at compile time: ● Sorry? But the same variable can hold different sub type objects at run time! – Indeed! We can define variables that may hold e.g. any derived type: – .Net differs the static (Object) and the dynamic type (Car) of an instance. – The idea of static/dynamic types is used for run time polymorphism in .Net. double sum = 5.2; // Type name "double" must be explicitly written for the variable sum. int count = 42; // count is of type int, we can only perform int operations on it! Object o = new Car(); // Type Car is derived from type Object. The Type System in .Net 1 (presented in C#1) – Part I
  • 4. 4 4 ● Esp. object-based collections rely on the cosmic hierarchy of .Net's type system: everything is an Object: – .Net 1 collections: Hold items of static type Object, their dynamic types can vary. ● In fact collections must be able to hold any type in order to be versatile. – .Net 1 "resorted" to run time polymorphism (i.e. Liskov Substitution Principle (LSP)) to get this versatility. – So in a .Net 1 collection, objects of any dynamic type can be stored. ● Object-based collections work great, as long as... – we'll only store objects of dynamic types that dependent code awaits, – we'll only cast down to dynamic types that dependent code put in, – we'll never put mixed unrelated dynamic types into the same collection, – well as we don't fall into a type problem during run time. ArrayList lines = new ArrayList(File.ReadAllLines("/Library/Logs/Software Update.log")); // File.ReadAllLines() was introduced with .Net 2! object item1 = lines[0]; object item2 = lines[1]; // We have to use cast contact lenses to get the dynamic types out of the objects: string text1 = (string)item1; // Access string's interface: int result = text1.IndexOf('g'); // We can also cast directly from the index notation: string text2 = (string)lines[1]; The Type System in .Net 1 (presented in C#1) – Part II
  • 5. 5 5 ● The problem or lack in the type system using LSP can be presented with the just created collectionlines: ● The problem is that we as programmers have to know about the contained dynamic types (strings and not Cars in lines). – Whenever Object is used in an interface (the return value of lines' indexer), some convention must be around. – This convention describes the dynamic type, we're really dealing with (strings and not Cars). – The contributed programers have just to obey the convention... ;-) ● We as programmers have to cast down (or unbox) to the type we await. – The cast is needed to access the interface of a static type (e.g. car.StartEngine()). – These casts indicate that the programer knows more than the compiler! – The compiler wears "cast contact lenses"; it can't type check, it trusts the programmer! – These casts are type checked at run time, so they are consuming run time! – Type errors (an item of lines was casted to Car instead of string) will happen at run time, not at compile time. object item1 = lines[0]; // But, these are not the awaited types, we can't deal with Cars, we await strings! // This cast will fail! An InvalidCastException will be thrown! Car car = (Car)item1; car.StartEngine(); public class Car { public void StartEngine() { /* pass */ } } The Type System in .Net 1 (presented in C#1) – Part III
  • 6. 6 6 ● Object-based collections have an interesting feature: we can beheterogeneous collections: – In a heterogeneous collection every item can have any different dynamic type: ● It works, but heterogeneous collections are tricky: developers need to know, on which indexes objects of certain types reside. ● Heterogenous collection should be avoided! Strive to using homogenous collections or other solutions! ArrayList objects = new ArrayList(); // Since each item is of type object, we can add any object to an ArrayList: objects.Add("aString"); // String objects.Add(42); // int objects.Add(new object()); // object objects.Add(new [] {1, 2, 3, 4}); // int[] foreach(object item in objects) { Console.WriteLine(item); } // This statement will fail, we can't deal with string, on index 1 an int was stored! // An InvalidCastException will be thrown! string result = (string)objects[1]; Homogeneous and heterogeneous Collections
  • 7. 7 7 ● What could we do close the lack in the .Net 1 type system to stay typesafe? ● We could use strictly typed arrays as collections if possible, they're not object-based and therefore typesafe: – However, arrays can not be used, when the collection in question needs to be modified (enlarged or downsized) after creation. ● We could create own, typesafe not object-based collections as UDTs (e.g. a special string-list for the discussed example). – In .Net we could resort to so called specialized collections in the namespace System.Collections.Specialized, e.g. StringCollection. ● But in the world of collections, there is a much better way to work in a typesafe manner: generic collections! // Create an array that hold strings: string[] lines = File.ReadAllLines("/Library/Logs/Software Update.log")); // With arrays we don't need casts, instead we can directly access lines' items as string objects: string text1 = lines[0]; // Access string's interface: int result = text1.IndexOf('g'); // Create a specialized StringCollection: StringCollection lines = new StringCollection(); lines.AddRange(File.ReadAllLines("/Library/Logs/Software Update.log")); // With the specialized StringCollection we don't need casts, instead we can directly access lines' items as string objects: string text1 = lines[0]; // Access string's interface: int result = text1.IndexOf('g'); The Type System in .Net 1 – Some Remedy
  • 8. 8 8 ● Let's improve our problematic code with the generic collection List<T>: ● .Net 2 introduced generic types to get rid of the presented type problems. – Generic types are types that leave a part of their type information open. – Generics are an outstanding feature in .Net 2. ● Generics (here List<T>) leave type information open? How should this help me out? – The open type information is accessible by type parameters (here T). – As programmers we can fill the type parameters by concrete type arguments (here string). – By setting type arguments of a generic type we create another type, the constructed type (List<string> in this case). ● The full name of the constructed type is List<string>! – => Net effect: The type argument (string) will be of static type, so the formerly open type information can be checked by the compiler. – In the end typesafety means that types are checked by the compiler at compile time and no longer at run time. // Create a generic List that holds strings: List<string> lines = new List<string>(File.ReadAllLines("/Library/Logs/Software Update.log")); // This time we don't need casts, instead we can directly access lines' items as string objects: string text1 = lines[0]; // Access string's interface: int result = text1.IndexOf('g'); // The generic type List<T>: public class List<T> { // (members hidden) public void Add(T item) { /* pass */ } } // This time we'll get a compile time error: Car car1 = lines[1]; // The type argument in lines was string, not Car! // Cannot convert string to Car. car1.StartEngine(); Generics to the Rescue
  • 9. 9 9 ● .Net's generic collections live in the namespace System.Collections.Generic. ● The generic counterpart of the collection ArrayList is List<T>, T is the type parameter. – List<T>'s interface is set to the open type T in parameter- and return-types of methods. – The type parameter T acts as a placeholder for the actual type argument. ● When a type is constructed, T is replaced by a type argument (the result is the constructed type). – List<string>'s interface is set to the static type string in parameter- and return- types of methods. ● The idea of generics is to use types (i.e. not values) as arguments! – The typesafty we got is that generics move type run time errors to compile time errors. // The generic type List<T>: public class List<T> { // (details hidden) public void Add(T item) { /* pass */ } public List<T> GetRange(int index, int count) { /* pass */ } } // The constructed type List<string> has following interface: public class List<string> { // (details hidden) public void Add(string item) { /* pass */ } public List<string> GetRange(int index, int count) { /* pass */ } } // Create a generic List that holds strings: List<string> lines; List T The UML represents generic types as parameterized classes. Generics – Overview List<T -> string> «bind» <T -> string> List<string> implicit binding against a type argument explicit binding against a type argument
  • 10. 10 10 ● It is also possible to define generic types, whose type argument is another generic type. – E.g. we can define a list of lists, i.e. a collection of collections, which is effectively a two-dimensional array or matrix. – Such collections are better than multidimensional arrays in some aspects: ● They offer the same concept to express rectangular as well as jagged arrays. ● "Real" collections are very flexible, as elements can be added and removed (or: the matrix' dimensions can be enlarged and shrank). ● The .Net framework as well as Java do also support generic types having two or more type parameters: – E.g. with the type SortedDictionary<TKey, Tvalue> (this type will be discussed later): ● To understand collections in Java, C++ and .Net it is required to understand alsoadvanced generics. // Creating a SortedDictionary object: SortedDictionary<string, int> aDictionary = new SortedDictionary<string, int>(); aDictionary.Add("fortytwo", 42); // The generic type SortedDictionary<TKey, TValue>: public class SortedDictionary<TKey, TValue> { // (members hidden) /* pass */ } // A jagged array in C# as matrix: int[][] matrix = new int[3][]; matrix[0] = new[] {1, 2, 3, 4}; matrix[1] = new[] {6, 7}; matrix[2] = new[] {8, 9, 0}; Console.WriteLine("Item: {0}", matrix[1][0]); // >Item: 6 // A list of lists of int as matrix: List<List<int>> matrix = new List<List<int>>(); matrix.Add(new List<int>{1, 2, 3, 4}); matrix.Add(new List<int>{6, 7}); matrix.Add(new List<int>{8, 9, 0}); Console.WriteLine("Item: {0}", matrix[1][0]); // >Item: 6 Slightly advanced Generics
  • 11. 11 11 ● Hence, we'll use generic types whenever appropriate. We'll define following substitutes for already introduced collections: – ICollection → ICollection<T> – IList → IList<T> – ArrayList → List<T> – IEnumerable → IEnumerable<T> – IEnumerator → IEnumerator<T> – .Net's framework design guidelines suggest using only generic collection types in public interfaces. ● From object-based to generic collections: IList names = new ArrayList(); names.Add("James"); names.Add("Miranda"); // Get the values back (object-based collection: static type Object): object name1 = names[0]; // "James" object name2 = names[1]; // "Miranda" string name1AsString = (string)name1; // Cast the string out of the object. string name2As = (string)names[1]; // Cast directly from the index notation. names[1] = "Meredith"; Console.WriteLine(names[1]); // >Meredith IList<string> names = new List<string>(); names.Add("James"); names.Add("Miranda"); // Get the values back (generic string-collection: static type string): string name1 = names[0]; // "James" string name2 = names[1]; // "Miranda" names[1] = "Meredith"; Console.WriteLine(names[1]); // >Meredith The better Type System – from object-based to generic Collections
  • 12. 12 12 ● C++ templates are, at least principally, C++' equivalent to .Net's and Java's generics. – C++ provides the template std::vector<T> (<vector>), which is functionally equivalent to .Net's List<T>: – Before C++ had templates, void*-based collections have been used, incl. cast contact lenses. - This is still true for C. ● void*-based collections are the functional equivalent to object-based collections! ● Objective-C and many scripting languages use so calleddynamic typing instead of generic or object-based structures. – (We're not going to discuss these concepts in this course.) // names is a vector containing string-elements. std::vector<std::string> names; names.push_back("James"); names.push_back("Miranda"); // Get the values back (template string-container: static type std::string): std::string name1 = names[0]; // "James" std::string name2 = names[1]; // "Miranda" names[1] = "Meredith"; std::cout<<names[1]<<std::endl; // >Meredith // in h-file <vector> template <typename T> class vector { // (details hidden) public: void push_back(const T& newItem); }; The Collection Type System of the C++ STL
  • 13. 13 13 ● The story about generic collections in Java is somewhat advanced,but Java programmers should know these facts. – A good way to understand Java's generics (and the problems that come with it) is to compare them to, e.g., .Net's generics. ● Here we have basically the same generic class in Java and C#: – The definition of instances of these classes has almost the same syntax in Java and C#: ● In Java we can only use reference types as type arguments for generic types. E.g. we can not create MyList<int> or MyList<double>. – As we know the idea behind generics is to have typesafty. So the last statements won't compile respectively: The Collection Type System on the Java Platform – Part I // Java public class MyList<T> { public List<T> items = new ArrayList<T>(5); } // Java stringList.items.add("Frank"); // OK for the compiler! A string literal can be set, because items is a List<String>. stringList.items.add(42); // Invalid for the compiler! Generics are typesafe! An int literal can't be set, because items is not a List<Integer>. MyList<String> stringList = new MyList<String>(); MyList<Integer> intList = new MyList<Integer>(); MyList<string> stringList = new MyList<string>(); MyList<int> intList = new MyList<int>(); // C# public class MyList<T> { public IList<T> items = new List<T>(5); } // C# stringList.items.Add("Frank"); // OK for the compiler! See explanation for Java above. stringList.items.Add(42); // Invalid for the compiler! See explanation for Java above.
  • 14. 14 14 ● The difference between Java and .Net is that different things are generated at compile time. – A compiler creating .Net IL code will produce a so called constructed type for each "filled out" generic type in the code: – A compiler creating Java bytecode will just erase the type argument and will fall back to an object-based type: ● This compilation step is called type erasure. The resulting type (w/o generic type parameters) is called the raw type of the generic type. ● Often this isn't a problem in Java, because compile time typesafety is fine, but it hurts the run time typesafety! ● Ouch! But Java provides a means to reestablish run time typesafety: run time type checked collection wrappers. The Collection Type System on the Java Platform – Part II stringList.items.add("Frank"); // Ok as before! ((MyList)stringList).items.add(42); // Huh? Casting (cast contact lenses) to the raw type and adding an int: ok for compiler and at run time! String itemAt1 = stringList.items.get(1); // Bang! Getting the int at the index one via the generic type: ok for the compiler but crashes at run time! // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String type construction of a .Net IL compiler // Java MyList<String> stringList = new MyList<String>(); MyList<Integer> intList = new MyList<Integer>(); public class MyList { // Raw type public List items = new ArrayList(5); } type erasure of a Java bytecode compiler // C# MyList<string> stringList = new MyList<string>(); MyList<int> intList = new MyList<int>(); public class MyList<string> { // Constructed type public IList<string> items = new List<string>(5); } public class MyList<int> { // Constructed type public IList<int> items = new List<int>(5); }
  • 15. 15 15 ● Java provides the class Collections with some static methods (simple factories) to create run time type checked collections. – A present collection needs to be passed to Collections.checked...() and a new collection wrapping the passed one will be returned. – Let's wrap MyList's encapsulated List to be a checked List with Collections.checkedList(): ● More simple factories can be found in the class Collections as static methods (checkedSet(), checkedMap() etc.). – The return type of all of these simple factories are just interface types, the type checked implementations are always hidden. – So the UML diagram of the relations between the contributing types looks like so: ● Run time type checked wrappers were added to the JDK in order have compatibility w/ non-generic collections, retaining compile time typesafty of generics and having run time typesafety. – There is an initiative in the Java community to introduce generic types with constructed types into Java: reified generics. – Mind that run time type checking is costly! The Collection Type System on the Java Platform – Part III stringList.items = Collections.checkedList(stringList.items, String.class); // Wrap items, so that it can only deal with strings at compile time. stringList.items.add("Frank"); // Ok as before! It was already checked by the compiler. ((MyList)stringList).items.add(42); // Bang! An int can't be added to a list that is only allowed to contain Strings! String itemAt1 = stringList.items.get(1); // Will not be reached at all! <<interface>> List HiddenCheckedListImplementation exposes implements Collections + checkedList(list : List<T>, type : Class<T>) : List<T> instantiates T
  • 16. 16 16 ● Up to now, we discussed relatively simple indexed and sequential collections. ● Besides indexed and sequential collections there also exist so calledassociative collections. ● In opposite to indexed and sequential collections,associative collections inspect the stored objects. – E.g. the indexed collection ArrayList just stores references to objects, but it does never, e.g., call methods on these objects. ● For indexed and sequential collections the contained items are said to be transparent. – Associative collections have to inspect stored objects for equivalence or equality in order to provide very mighty features. ● Let's start by analyzing a problem, which can be solved with associative collections. Indexed, sequential and associative Collections
  • 17. 17 17 ● Let's assume that we have to handle color names and figure out the belonging to HTML color codes: ● Of course the task can be solved this way, but the solution is based on a possiblyfragile assumption: – The two separate arrays need to hold belonging to values at the same indexes! – Basically we've to go through all items sequentially and compare (Array.IndexOf()). – We say the association is index-based. ● The presented algorithm is a so called lookup-algorithm (lookup). – Lookups are used very often in programming. – A problem of lookups is that separate collections (colorNames and htmlColorCode) need to be evaluated (like tables in relational databases). – Modern collection frameworks provide dedicated collections to cover lookups in a comfortable manner: associative collections. // C# // Here we have two arrays that hold color names and HTML color codes: string[] colorNames = {"Blue", "Red", "Green"} ; int[] htmlColorCodes = {0x0000FF, 0xFF0000, 0x00FF00}; // With the information given, the task to pick an HTML color code from a color name is trivial: Because the // index of the color name matches the index of the color HTML code, we can formulate a simple algorithm: int indexOfRed = Array.IndexOf(colorNames, "Red"); int colorCodeOfRed = htmlColorCodes[indexOfRed]; Console.WriteLine("Color code for Red: {0:X6}", colorCodeOfRed); // >Color code for Red: FF0000 colorNames0x0000FF 0xFF0000 0x00FF00 "Blue" "Red" "Green" htmlColorCodes 210 matching indexes Example – Color Names to HTML Color Codes – Part I
  • 18. 18 18 colorNamesToColorCodes ● Associative collections abstract the usage of multiple collections to solve the just presented lookupin an intuitive manner: – Here .Net's associative collection SortedDictionary<string, int> is shown (it implements IDictionary<string, int>): – The association of both, color names and color codes, is available via the single collection colorNamesToHtmlColorCodes. ● We have to rethink our termination: associative collections associate a key (color name) to a value (color code). – The association is key-based and no longer index-based. – The internal "organization" is key-value-pair-based. – In a sense an array is nothing but an associative collection that associates a value with an index (mind the []-syntax). – In fact real problems often involve associating values with other values, e.g.: White pages, thesaurus, document index. ● The .Net collection KeyedCollection<K, T> allows the lookup of data stored in the value (i.e. there are no key-value-pairs). // Associating color names with HTML color codes using a SortedDictionary: IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>(); colorNamesToColorCodes.Add("Blue", 0x0000FF); colorNamesToColorCodes.Add("Red", 0xFF0000); colorNamesToColorCodes.Add("Green", 0x00FF00); int colorCodeOfRed = colorNamesToColorCodes["Red"]; Console.WriteLine("Color code for Red: {0:X6}", colorCodeOfRed); // >Color code for Red: FF0000 0x0000FF 0xFF0000 0x00FF00 "Blue" "Red" "Green" Key-value-pair {"Green", 0x00FF00} Example – Color Names to HTML Color Codes – Part II ● Mind how the term key (primary/foreign key) is also applied in the design of databases. ● Indeed KeyedCollection is a very useful collection. However, it is not a classical associative collection, because it uses linear search (it is backed by a List and calls Contains() on that List potentially for each item). The abstract class KeyedCollection needs to be specialized (overriding GetKeyForItem(), i.e. we have the template method design pattern here) to get the key from the managed item/value.
  • 19. 19 19 ● In many scripting languages associative collections havespecial syntactical support. – The names "hash", "hashmap" or "associative array" are common in scripting languages. – In JavaScript every object is a collection of property-value-pairs per se. An array is also an associative collection: ● In other platforms associative collections are often called Maps (Java) or Dictionaries (Cocoa, .Net). – Esp. the term "Map" is taken from the phrase "to map something", which means "to associate something". – The term "hash" still needs to be clarified in this context: we have to understand how associative collections work. ● We'll start discussing equivalence-based associative collections and then equality-based associative collections using hashing. # E.g. in Ruby associative collections are supported as "hashes" with integrated syntactical support. # Just initialize a variable with a list of key => value pairs: colorNamesToColorCodes = {"Blue" => 0x0000FF, "Red" => 0xFF0000, "Green" => 0x00FF00} # The items can be accessed with the []-operator: printf("Color code for Red: %06X", colorNamesToColorCodes["Red"]) # >Color code for Red: FF0000 // JavaScript // Create associative collection as object with properties: var colorNamesToColorCodes = new Object(); colorNamesToColorCodes.Blue = 0x0000FF; colorNamesToColorCodes.Red = 0xFF0000; colorNamesToColorCodes.Green = 0x00FF00; console.log("Color code for Red: " +colorNamesToColorCodes.Red.toString(16)); // >Color code for Red: FF0000 // JavaScript // Create associative collection as associative array: var colorNamesToColorCodes = new Object(); colorNamesToColorCodes["Blue"] = 0x0000FF; colorNamesToColorCodes["Red"]= 0xFF0000; colorNamesToColorCodes["Green"]= 0x00FF00; console.log("Color code for Red: " +colorNamesToColorCodes["Red"].toString(16)); // >Color code for Red: FF0000 Associative Collections in other Languages
  • 20. 20 20 ● New about associative collections is that associative collections inspect the items they hold. – I.e. associative collections operate on contained items: they call methods on the keys of the contained key-value-pairs. – Associative collections need to compare the keys they hold. – In opposite to other collections, items are got and set by analyzing their relationships. ● Associative collections are very powerful and allow writing elegant/readable algorithms to solve complicated problems. – Associative collections could be implemented with two arrays as shown before, but this would be inefficient for common cases. – A clever internal organization of associative collections is required to allow efficient access and modification of contained items. ● There are two general ways to organize items (i.e. their keys) in an associative collection: – (1) By equivalence. I.e. by their relative order/order-relationship, such as less than and greater than. – (2) By equality. I.e. by hash-codes and the result of the equality check (methods hashCode()/equals() (Java) or GetHashCode()/Equals() (.Net)). ● In this and the next lecture we're going to discuss associative collections that organize their keys byequivalence. – This is the case for SortedDictionary, so we'll discuss .Net's SortedDictionary. Organization of Items in associative Collections ● It should be mentioned that some methods of list- types already needed to inspect the contained items to function, e.g. Contains(), Remove(), IndexOf(). These methods use equality to inspect/compare values.
  • 21. 21 21 ● Create the empty SortedDictionary<K, V> colorNamesToColorCodes: ● Then we can add three key-value-pairs like so: ● Get the value of a key, i.e. make a lookup with the indexer ([]-operator): ● Check, whether an entry with a certain key is already existing with the method ContainsKey(): ● Iteration: The internal organization is key-value-pair-based, so IDictionary's iterator produces an iterator of key-value pairs. C# – collection initializers for dictionaries // Apply a collection initializer on a SortedDictionary: IDictionary<string, int> colorNamesToColorCodes2 = new SortedDictionary<string, int> { {"Blue", 0x0000FF}, {"Red", 0xFF0000}, {"Green", 0x00FF00} }; IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>(); colorNamesToColorCodes.Add("Blue", 0x0000FF); colorNamesToColorCodes.Add("Red", 0xFF0000); colorNamesToColorCodes.Add("Green", 0x00FF00); int valueForBlue = colorNamesToColorCodes2["Blue"]; // >0x0000FF Operations on IDictionarys – Part I // IDictionary<string, int> implements IEnumerable<KeyValuePair<string, int>>. // Iteration yields KeyValuePair<string, int>-items: foreach (KeyValuePair<string, int> item in colorNamesToColorCodes) { Console.WriteLine(item); } bool blueAlreadyPresent = colorNamesToColorCodes2.ContainsKey("Blue"); // >true ● Because colorNamesToColorCodes is virtually a SortedDictionary, the iteration will yield the items in the order sorted by their keys.
  • 22. 22 22 ● Trying to query the value for a key that doesn't exist will throw a KeyNotFoundException: – To avoid these "surprises" check the key for existence (with ContainsKey()), before it is looked up. ● Adding a pair for an already existing key will throw an ArgumentException. – .Net dictionaries don't allow having a key with multiple values. (However, the C++' STL-container std::multimap can handle this.) ● The indexer allows adding new entries as well as replacing values of existing key-value-pairsand reading values: ● We can get the current count of elements stored in the dictionary (Count is required by implementing ICollection<T>): colorNamesToColorCodes.Add("Blue", 17); // Throws ArgumentException: a key-value-pair with the same key already exists in the dictionary. colorNamesToColorCodes["Blue"] = 17; // OK! Replaces "Blue"'s value 0x0000FF with 17. colorNamesToColorCodes["Yellow"] = 0xFFFF00; // Adds the new key-value-pair {"Yellow", 0xFFFF00}. if (colorNamesToColorCodes.ContainsKey("Yellow")) { // Checking the existence of the key "Yellow". // Use the indexer to retrieve "Yellow"'s value: Console.WriteLine("Color code for Yellow: {0:X6}", colorNamesToColorCodes["Yellow"]); // >Color code for Yellow: FFFF00 } Console.WriteLine(colorNamesToColorCodes.Count); // >4 Operations on IDictionarys – Part II int valueForOrange = colorNamesToColorCodes2["Orange"]; // Throws KeyNotFoundException: a key-value-pair with that key doesn't exists in the dictionary.
  • 23. 23 23 ● Now its time to understand how SortedDictionarys work basically, we'll discuss it in depth in the next lecture. – We have to clarify, how SortedDictionary knows if a key is already present or not! - It needs to compare keys somehow! ● The question is: "How does SortedDictionary know if two keys are equal?" – A part of the answer is that SortedDictionary doesn't know, if two items are equal, but it knows if two items are equivalent! – SortedDictionary's comparison is based on the order-relationship among items. This is called equivalence comparison. ● The order-relationship can be expressed by evaluating two values one beingless than, greater than or equal the other. – If of two values one is neither less than nor greater than the other the values are said to be equivalent (Not equal!). – .Net provides a way for types to declare equivalence comparability: implementing the interface IComparable/IComparable<T>. – (The C++ STL requires types to override operator< to implement equivalence comparability.) ● Now we are going to understand how IComparable/IComparable<T> has to be implemented for own UDTs. SortedDictionary and Equivalence Comparison
  • 24. 24 24 UDTs as Keys of associative Collections – Part I ● Up to now we've only used objects of builtin types for the keys of associative collections (e.g. string). – Now we are going to explore how to use keys of our own types. Let's do this with the UDT Car: – Obviously it doesn't work this way! - What did we miss? ● The problem is that nobody (esp. SortedDictionary) knows, how to compare Cars! – One way to implement this: Car could itself know, how it can be compared – we've to implement IComparable<Car> in Car: – IComparable<T>.CompareTo() should return a value less than 0, if this < other, a value greater than 0, if this > other and otherwise 0. ● For Car we'll delegate the implementation of IComparable<Car>.CompareTo() to Car's property Name, Name is of type string (string implements IComparable<string>). – With this implementation of Car SortedDictionary<TKey, TValue> works as expected: public class Car { public string Name {get; set;} } IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>(); // Adding the first item won't require to compare items: carToManufacturer[new Car{ Name = "Focus" }] = "Ford"; // Will throw ArgumentException: Object doesn't implement IComparable! carToManufacturer[new Car{ Name = "Auris" }] = "Toyota"; IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>(); carToManufacturer[new Car{ Name = "Focus" }] = "Ford"; // OK! carToManufacturer[new Car{ Name = "Auris" }] = "Toyota"; public class Car : IComparable<Car> { // (members hidden) public int CompareTo(Car other) { // Very simple implementation that compares the Cars' Name fields: return this.Name.CompareTo(other.Name); } } ● The associative collection does really look into the items: just set a breakpoint into the Car. CompareTo() method!
  • 25. 25 25 UDTs as Keys of associative Collections – Part II ● But there are cases, in which implementing IComparable<T> is no option to make types usable as keys: – (1) if we can not modify the type in question, e.g. if it is a type of a 3rd party library, – (2) if the type in question does already implement IComparable<T>, but the implemented comparison doesn't meet our needs, – (3) if the type doesn't implement IComparable<T> at all. ● Let's assume that we want to use Cars as keys by case insensitive comparison of their Name property. – We could change the implementation of Car.CompareTo(), but this would hurt the Open-Close Principle (OCP). – Effectively we have the case (2). The present implementation of IComparable<Car> doesn't meet our needs. ● To cover these cases there is another way to implement comparison:implement comparison in a different type (not in Car). – I.e. we can implement a dedicated type that has only one responsibility: comparing Cars. Such a type is called comparator. – The .Net framework provides a special interface to support such special comparison types: IComparer/IComparer<T>. – Now it's time to implement a comparer to compare the case insensitive Name of Cars. ● If a type does not implement IComparable<T>, and we try to add at least two instances of that type used as key into a SortedDictionary, an ArgumentException will be thrown.
  • 26. 26 26 UDTs as Keys of associative Collections – Part III ● The type SortedDictionary<TKey, TValue> accepts an object of type IComparer<TKey> in one of its ctors: – As can be seen the passed comparer refers to the type TKey. ● The comparer to specify in the ctor determines, how Cars are getting compared. The comparer looks like this: ● Here we'll finally pass an instance of the created CaseInsensitveCarComparer to SortedDictionary's ctor: public class CaseInsensitiveCarComparer : IComparer<Car> { public int Compare(Car lhs, Car rhs) { // Very simple implementation that compares the Name // fields of two Cars ignoring the case: return string.Compare(lhs.Name, rhs.Name, true); } } // The generic type SortedDictionary<TKey, TValue>: public class SortedDictionary<TKey, TValue> { // (details hidden) public SortedDictionary(IComparer<TKey> comparer); } // Create a dictionary and specify the special comparer in the ctor: IDictionary<Car, string> carToManufacturer = new SortedDictionary<Car, string>(new CaseInsensitiveCarComparer()); carToManufacturer[new Car{ Name = "Cortina" }] = "Ford"; // This won't add another "cortina", because the specified comparer evaluates "Cortina" and "cortina" as being equivalent. carToManufacturer[new Car{ Name = "cortina" }] = "Lotus"; // Will set "Cortina"'s value to "Lotus". Console.WriteLine("Count of items: {0}", carToManufacturer.Count); // >Count of items: 1
  • 27. 27 27 Controlling String-Key Comparison ● If we use strings as keys (i.e. not a UDT like Car), we can use predefined comparers to compare case insensitively. – The .Net framework provides a set of predefined StringComparer objects in the type StringComparer. – Let's rewrite the color code example for case insensitive color names: – We can do the same with Java's TreeMap managing string-keys case-insensitively using a special Comparator: – If we like to exploit the sorting of the Map and want the keys to be sorted in descending order, just reverse the Comparator: // Create a dictionary and specify the case insensitive string comparer in the ctor: IDictionary<string, int> colorNamesToColorCodes = new SortedDictionary<string, int>(StringComparer.OrdinalIgnoreCase); colorNamesToColorCodes.Add("Green", 0x00FF00); // Because of the case insensitive comparison "Green" and "green" are seen as equivalent key objects: int colorCodeOfGreen = colorNamesToColorCodes["green"]; Console.WriteLine("Color code for Green: {0:X6}", colorCodeOfGreen); // >Color code for Green: 00FF00 // Create a map and specify the case insensitive string comparator in the ctor: Map<String, Integer> colorNamesToColorCodes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); colorNamesToColorCodes.put("Green", 0x00FF00); // Because of the case insensitive comparison "Green" and "green" are seen as equivalent key objects: int colorCodeOfGreen = colorNamesToColorCodes.get("green"); System.out.printf("Color code for Green: %06X%n", colorCodeOfGreen); // >Color code for Green: 00FF00 // Create a map and specify the case insensitive string comparator in the ctor, the sorting should be descending: Map<String, Integer> colorNamesToColorCodesDescending = new TreeMap<>(Collections.reverseOrder(String.CASE_INSENSITIVE_ORDER)); ● Creating a reversed Comparer by passing an existing Comparer to Collections.reverseOrder() is an example of the decorator pattern. A present Comparer is decorated with extra functionality and the new object has the same interface than the one being decorated.