Czytając blog Ayende Rahien-a natknąłem się na dość ciekawą technikę przetrzymywania stringów w pamięci. “String Interning”.

Stringi wrzuca się do tablicy. Jeżeli dany string znajduje się już w tablicy przekazujemy tylko wskaźnik do istniejącego stringa jeżeli nie istnieje wrzucamy go do pamięci i przekazujemy wskaźnik.

Technika ta pozwala zaoszczędzić pamięć i przyspiesza porównywanie stringów [Sprowadza porównywanie do porownywania zwyklych referencji a nie obiektów. Jak wiemy porownywanie stringów to operacja o zlozonosci obliczeniowej O(n) natomiast porównywanie wskaźników to O(1).

Java i .Net stosuje ten mechanizm automatycznie w momencie tworzenia literałów.Python składuje tak małe stringi.

   12             int i = 1;

   13             int j = 1;

   14 

   15             String s = "jakis string";

   16             String a = "jakis string";

   17 

   18 

   19             Console.WriteLine((Object)s == (Object)a);

   20 

   21             Console.WriteLine((Object)i == (Object)j);

W przykładzie tym 1 porównanie zwróci wartość true. Oznacza to że oba obiekty wskazują w to samo miejsce. W momencie tworzenia stringa s została przeszukana tablica stringów. Jako że nie było w niej stringu “jakiś string” została ona wrzucona do tej tablicy i został przekazany wskaźnik. Stringowi a natomiast został przypisany wskaźnik do miejsca na stercie na które wskazuje s ponieważ ta wartość już jest w tablicy. [Tak to działa w znacznym uproszczeniu].

Rzutowanie na Object jest wykonane po to by odwołać się do przeciążenia operatora w klasie bazowej (==) który porównuje referencję.

2 porównanie zwraca wartość false. Przykład ten jest tylko po to by ukazać że interning nie jest stosowane dla np intów. A to dlatego że są one w przeciwieństwie do literałów obiektami immutable [zmiennymi]