In which scenario is it recommended to use KeyedCollection instead of a Dictionary?

7

I did not know of the existence of KeyedCollection until you see this #

asked by anonymous 27.03.2015 / 11:58

2 answers

6

You should use in the situation that you need to access the elements of this collection at O (1) (find the which desires essentially at the same time, no matter the size of the collection) by both the position of the element and the key. Either you need either the collection listed in the order that it was being added or find an element within it quickly.

List

At List it is easy to maintain the order of data entry and access them according to their position. A list looks like an array . Simply index and you arrive at the element very quickly only with a quick calculation of the memory location. In a way we can say that index is the key to this collection. If you try to find a value in this list you will have an O (N) complexity, that is, you will have to potentially go through the entire list to find what you want.

Dictionary

In Dictionary the storage is done through functions of hash >, that is, the key is computed and gets a number that will be used to position the element in an inner structure that will store the collection. So it's very quick to find an element by its key in almost every case. Just do the calculation of the key to find your "magic number" and there you position where the element is, you do not have to go through the other elements (there are cases that need to go through some elements because there may be a collision but this is another subject and I will not go into details, in good hash this almost does not happen). The problem is that if you want to sequentially enumerate these elements, nothing guarantees how it comes, has no order. And because it has no definite order, you can not pick up an element by its position of addition. You can not get the first or last element added to the collection.

Best of worlds

KeydCollection resolves this. You can do both.

But how can he do this?

In computing, everything is tradeoff . You have to choose what you will give up to have an advantage. In this case you will relinquish memory. This collection roughly maintains a List and Dictionary internally. By this it manages to have the two characteristics. Of course this consumes more space.

One way to achieve this is to have a list that is added in order and have a table hash which has the key as defined in KeydCollection and its value (remember that a dictionary uses a key and value pair) is the position in the list where this element is. So you do not need to duplicate the content in both structures.

Of course I'm talking about a hypothetical implementation, this is implementation detail (if you want to see how it's actually implemented, the source is available ). In an ideal situation it should have a higher optimization, especially if the size of the value is smaller than the index size of the list. But I doubt this is done.

Using this class

As can be seen in the documentation of this collection, it is abstract, you can not actually use it. One should create a derivative and overwrite an abstract method to find a key in the middle of a set value. Because it is abstract, it needs a concrete implementation.

A concrete implementation example of the class allowing it to be used generically, that is, the key is defined by an anonymous function and avoid having to be deriving the class whenever it needs a different criterion, which should be very common to be different in each case when using KeyedCollection .

Note that in this class you do not specify the key and value, as in Dictionary . You specify the value of the element. The key will be obtained by any calculation defined within the class in the GetKeyForItem() method. This calculation can take the value as a whole, can take a member of the value, or can make a complex composition of what is found in the value.

    
27.03.2015 / 12:27
6

Actually KeyedCollection is Dictionary where you choose how to mount the index.

Notice that in the example of the response mentioned I use something like this:

public class MortoCollection : KeyedCollection<String, Morto>
{
    protected override string GetKeyForItem(Morto item)
    {
        return item.NrCpf.ToString();
    }
}

Usage is almost equal to Dictionary :

var morto = minhaCollection['12345678901'];

Using this way, I return the object whose morto is equal to Cpf to 12345678901 .

When to Use?

When you want to mount an object dictionary indexed by some object property. Unlike a List , where you need to use extensions to get objects by value (therefore, slower, since it is necessary to iterate the items one by one to get the value), KeyedCollection makes this get very element more simple.

    
30.03.2015 / 15:38