Skip to content

Instantly share code, notes, and snippets.

@sirkyven
Last active September 19, 2020 23:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sirkyven/84b2f0f09aea4dce6765ce29c954e4e7 to your computer and use it in GitHub Desktop.
Save sirkyven/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
// 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