W moim kodowaniu java często kończę z kilkoma Map<String,Map<String,foo>>
lub Map<String,List<String>>
, a następnie mam problem z zapamiętaniem, który Ciąg jest kluczem. Komentarz do deklaracji z //Map<capabiltyId,Map<groupId,foo>>
lub //Map<groupId,List<capabilityId>
, ale to nie jest najlepsze rozwiązanie. Jeśli String nie byłby ostateczny, tworzyłbym nowe klasy CapabilityId extends String
i GroupId extends String
, ale nie mogę. Czy istnieje lepszy sposób na śledzenie, która rzecz jest kluczem i może kompilator ją wymusić?Lepsze bezpieczeństwo typów w kolekcjach Java
Odpowiedz
Zamiast mieć CapabilityId
przedłużyć String
, CapabilityId
może zawierać pole String
o nazwie "id"; wtedy Twój Map
może być zdefiniowany jako Map<CapabilityId, Map<GroupId, Foo>>
, a możesz dostać się do indywidualnych pól identyfikacyjnych przez getId()
na swoich klasach kluczy.
Nie jestem pewien, czy sam bym to zrobił, ale jeśli tak, to prawdopodobnie to zrobię.
Można ograniczyć bałagan poprzez klasę abstract GenericId
z pola ID i getId()
metody i mają CapabilityId
i GroupId
dziedziczyć po nim.
To bardzo charakterystyczny komentarz Lincolna. –
Przyznaję, że wybieram się do Jerry'ego Pournelle "Jeśli tego potrzebujesz, potrzebujesz go źle", ale na odwrót. –
To jest dokładnie to, co zrobiłem wczoraj, aby wyśledzić wyciek pamięci; zamiast 150m obiektów String mogłem natychmiast zorientować się, która mapa nie była czyszczona, widząc, ile obiektów nnnnKey zostało utworzonych. – rhu
struny owijane w otoki-klas, jeśli chcesz:
class GroupId implements Comparable {
private String groupId;
public GroupId (String groupId) {
this.groupId = groupId;
}
...
}
Map<GroupId, List<CapabilityId>> m = ...
Dlaczego warto stosować Porównywalne? –
Utwórz klasę ID
które można podklasy, i który składa się z pola String
i wdrożeń equals()
i hashCode()
które używają tego pola.
Zamiast Map<String,List<String>>
należy użyć Multimap z Google/Google Guava Kolekcji
Dodawanie do innych odpowiedzi:
owinąć go.
To nie jest tylko rozwiązanie twojego problemu, ale ogólnie dobry pomysł, to jest uniknięcie prostych parametrów . Twój kod zyska czytelność, rozsądek i łatwość konserwacji. Możesz dodać do niego wszystkie miłe właściwości, np. zadeklaruj to @Immutable. Jak się dowiedziałeś, w ten sposób lepiej jest pamiętać i kontrolować. Jesteś właścicielem klasy i możesz robić z nią, co chcesz.
Umieściłbym wszystko w jednej klasie i użyłbym rozsądnych nazw pól/metod/argumentów.
public class GroupCapabilities {
private Map<String, Map<String, Group>> groupCapabilities;
public void addGroup(String capabilityId, Group group) {
Map<String, Group> groups = groupCapabilities.get(capabilityId);
if (groups = null) {
groups = new HashMap<String, Group>();
groupCapabilities.put(capabilityId, group);
}
groups.put(group.getId(), group);
}
public Map<String, Group> getGroups(String capabilityId) {
return groupCapabilities.get(capabilityId);
}
public Group getGroup(String capabilityId, String groupId) {
Map<String, Group> groups = groupCapabilities.get(capabilityId);
return (groups != null) ? groups.get(groupId) : null;
}
// Etc..
}
W ten sposób można zobaczyć przy nazwie metody/argumentu, czego oczekuje/zwraca.
Istnieje wiele sposobów, aby przejść na ten jeden (niektóre już wspomniano):
- Jak @Roman, owinąć ogólny rodzaj przeznaczenia w bardziej konkretnego typu, co daje silniejszą pisać. Silne dobre pisanie, IMO.
- Jako @nanda, użyj bardziej szczegółowego typu kolekcji. Biblioteka Java jest trochę słaba w tym obszarze. To zależy od tego, co czujesz na temat zależności.
- Jako @BalusC przenieś wszystkie icky stuff na icky klasy. Naprawdę nie usuwa problemu, ale go zawiera (jak w Ghostbusters).
Map<String,Map<String,foo>>
wygląda bardzo podobnie do klucza złożonego, tj. Klucza składającego się z dwóch części. Dlatego wprowadź niezmienną klasę złożonego klucza, czyli obiekt wartości reprezentujący obiekty wartości dwóch składników.
- 1. Polimorficzne parametry typów w kolekcjach ogólnych
- 2. W jaki sposób kopiowanie na kolekcjach zapisu zapewnia bezpieczeństwo wątków?
- 3. Lepsze konstruktora HTML w java
- 4. Java StringBuilder i Bezpieczeństwo wątków
- 5. MongoDB/Java: wpisz bezpieczeństwo w DBObjects
- 6. Każde skrzyżowanie w dwóch kolekcjach
- 7. Splice na kolekcjach
- 8. Dane "bezpieczeństwo" z java i hibernacji
- 9. Konstruktor Java używający generycznych typów
- 10. Lepsze powiadomienia w zasobniku
- 11. Lepsze autouzupełniania w VIM
- 12. Lepsze CSS w .NET?
- 13. "Lepsze" pływające w CSS
- 14. W jaki sposób łańcuch znaków Java jest niezmienny zwiększa bezpieczeństwo?
- 15. Porównaj mongo diff w dwóch kolekcjach
- 16. Zapisywanie obiektu Mongoose w dwóch kolekcjach
- 17. Suma wszystkich zliczeń w kolekcjach. Konto
- 18. LINQ: Użyj .Except() na kolekcjach różnych typów, czyniąc je wymienialnymi/porównywalnymi?
- 19. Przekazywanie podtypów w PHP - bezpieczeństwo i wydajność
- 20. Bezpieczeństwo wątku JTextArea.append
- 21. backbone.js Bezpieczeństwo
- 22. Bezpieczeństwo Cakephp
- 23. Wiosna Singleton Bezpieczeństwo wątków
- 24. Hadoop Bezpieczeństwo
- 25. static_cast bezpieczeństwo
- 26. Bezpieczeństwo PouchDB
- 27. Scala self type i this.type w kolekcjach wydanie
- 28. Możliwość generowania duplikatów Mongo ObjectId w dwóch różnych kolekcjach?
- 29. Bezpieczeństwo JavaScriptu?
- 30. Zamknięcia Java 8 i rozpoznawanie typów
Czy można użyć wyliczenia zamiast łańcucha? To może być przydatne, gdy masz dobrze zdefiniowane klucze. – Carl