Last active
September 19, 2020 23:12
-
-
Save venkman00/84b2f0f09aea4dce6765ce29c954e4e7 to your computer and use it in GitHub Desktop.
Various collection static initialization and important tradeoffs, notes from the https://youtu.be/lwp2RZ__0ko
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// notes from https://youtu.be/lwp2RZ__0ko | |
List<String> stringList = Collections.unmodifiableList(Arrays.asList("a", "b", "c")); | |
//SE 9+ | |
List<String> stringList = List.of("a", "b", "c"); | |
Set<String> stringSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c"))); | |
//SE 9+ | |
Set<String> stringSet = Set.of("a", "b", "c"); | |
Map<String, Integer> stringMap = new HashMap<>(); | |
stringMap.put("a", 1); | |
stringMap.put("b", 2); | |
stringMap = Collections.unmodifiableMap(StringMap); | |
//SE 9+ | |
Map<String, Integer> stringMap = Map.of("a", 1, "b", 2, "c", 3); | |
List.of() | |
List.of(e1) | |
List.of(e1, e2) | |
List.of(elements...) | |
Set.of() | |
Set.of(e1) | |
Set.of(e1, e2) | |
Set.of(elements...) | |
Map.of() | |
Map.of(k1, v1) | |
Map.of(k1, v1, k2, v2) | |
Map.of(k1, v1, k2, v2,...k10, v10) | |
//Map.of has limitation of 10 max entries, to want no restriction on accepting more number of key value pairs, we should | |
//Map.ofEntries and pass Entry object which contains key value pair. | |
import static java.util.Map.entry; | |
Map.entry(k, v) | |
Map.ofEntries(entry(k1,v1), entry(k2,v2),...); | |
Map<String, TokenType> tokens = Map.ofEntries( | |
entry("@", AT), | |
entry("|", VERTICAL_BAR), | |
... | |
); | |
//Idempotent Copying | |
List.copyOf(Collection) | |
Set.copyOf(Collection) | |
Map.copyOf(Map) | |
// Creation from Streams | |
Collectors.toUnmodifiableList() | |
Collectors.toUnmodifiableSet() | |
Collectors.toUnmodifiableMap(keyFunc, valueFunc) | |
Collectors.toUnmodifiableMap(keyFunc, valueFunc, mergeFunc) | |
class EmployeeDatabase { | |
List<Employee> employees; | |
public void setEmployees(List<Employee> newEmps) { | |
employees = newEmps; //bad since someone outside can modify newEmps, we don't want side effects. | |
employees = Collections.unmodifiableList(new ArrayList<>(newEmps)); | |
//SE 9+ <only makes a copy if it needs to, if the passed argument is unmodifiable it returns the same. | |
employees = List.copyOf(newEmps); | |
} | |
} | |
//Now consider: | |
employeeDB.setEmployees(List.of(alexis, brett, chris, dana)); | |
// This won't make an extra copy | |
// The copyOf methods won't make a copy if the list is already unmodifiable. | |
// Unmodifiability: | |
// Collections returned by the new static factory methods are unmodifiable | |
// --> attemtps to add, set, or remove elements throw UnsupportedOperationException | |
// What good is an unmodifiable collection? | |
// --> collections are often initialize from known values and never changed. | |
// --> can pass internal collection to client without fear of accidental modification | |
// --> easier to reason about an object if its fields are never modified. | |
// Unmodifiable vs Immutable | |
// --> the collection itself is unmodifiable | |
// --> if contents are modifiable, the whole thing is modifiable | |
// --> the whole thing is immutable only if the contents are immutable | |
// Randomized Iteration Order | |
// Iteration order for Set elments and Map Keys | |
// HashSet, HashMap: order is officially unspecified | |
// order is usually consistent across multiple JDK release cycles -- years | |
// inadvertent order dependencies can creep into code | |
// this code breaks when/if iteration order changes | |
// New Set and Map iteration order is randomized | |
// order can change from run of the JVM to the next | |
// goal: prevent code from inadvertantly acquiring iteration order dependencies. | |
// exisiting collections (HashSet, HashMap) iteration order is unchanged. | |
// use LinkedHashSet/LinkedHashMap for mutable collection with defined iteration order. | |
// Duplicates Disallowed | |
// Some APIs throws IllegalArgumentException if duplicates are encountered. | |
// Set.of, Map.of, Map.ofEntries | |
// these APIs are used like collection literals, where a duplicate is most likely an error | |
// this avoids mysterious bugs with "missing" entries | |
// also Collectors.toUnmodifiableMap(keyFunc, valueFunc) | |
// If you want to deduplicate without errors, use: | |
// Set.copyOf | |
// Collectors.toUnmodifiableSet | |
// Collectors.toUnmodifiableMap(keyFunc, valueFunc, mergeFunc) | |
Map<String, TokenType> tokens = Map.ofEntries( | |
entry("@", AT), | |
entry(";", SEMICOLON), //hard to find this kind of typos or errors | |
entry(";", COLON), | |
entry("$", DOLLAR) | |
); | |
// aha.. fancy ehe.. record has been introduced in Java 14 | |
// to create Data objects.. don't say to anyone looks someone in the team used | |
// Kotlin ha ha. | |
record Player(...) {} | |
record ScoringPlay(Player player, int score) {} | |
// suppose we want a Map<Player, Integer> with the total score of each player | |
List<ScoringPlay> scoringPlays = ... ; | |
Map<Player, Integer> playerScores = | |
scoringPlays.Stream() | |
.collect(Collectors.toUnmodifiableMap(ScoringPlay::player, | |
ScoringPlay::score, | |
Integer::sum)); | |
// Space efficiency | |
// Implementation classes hidden bidden static factory methods | |
// --> this allows choice of different implementations depending on size | |
// --> this can change from release to release without affecting applications. | |
// Data organization | |
// -> Singeltons for zero elements | |
// -> field-based implementations for small number of elements | |
// -> array-based for larger number of elements. | |
// Overhead of Set with two strings | |
// -> HashSet: 6 objects, 152 bytes | |
// -> Set.of: 1 object, 20 bytes | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment