equals()
. Help him implement the thread-safe dedup method by analogy with String.intern
, but not only for strings. public static Object dedup(Object obj) { }
java.util.concurrent
, recalled the wonderful method computeIfAbsent
. This method will perform the lambda passed to it in the parameter only if there is no key in the Map
, write its result and return it. If there is already such a key, the lambda will not be calculated, and the current value associated with the key will be returned. In addition, Kirill recalled, for ConcurrentHashMap
this method works atomically, which makes it very elegant to solve the problem. Satisfied Cyril wrote this code: private static final ConcurrentHashMap map = new ConcurrentHashMap(); public static Object dedup(Object obj) { return map.computeIfAbsent(obj, o -> o); }
String ipToString(byte[] ip) { return ip[0] + '.' + ip[1] + '.' + ip[2] + '.' + ip[3]; }
'.'
of type char
, added to the byte as an integer type. Replacing '.'
on "."
, Dima was so pleased with the successfully compiled code that he immediately launched it without testing. “Ahhhhhhh, Dima”, thought the JVM and gave out some nonsense instead of an IP address. Unlike Dima, the JVM knew exactly that in Java, the type byte
serves to store signed numbers, that is, all addresses that have octets greater than 127 will be represented in Java by negative numbers. By the rules of casting these numbers to int
, the negative sign of the number is the same as in the original byte. Oh, Dmitry, it was necessary to take additional measures in order to drop the symbolic part, for example: return (ip[0] & 255) + "." + (ip[1] & 255) + "." + (ip[2] & 255) + "." + (ip[3] & 255);
Random random = ThreadLocalRandom.current(); list.sort((o1, o2) -> { return random.nextBoolean() ? +1 : -1; });
Comparator
contract requires stability: when comparing two identical values, the comparison result should be the same. And in Marina’s implementation, the result for each pair is strictly random, which could easily lead to the exception of java.lang.IllegalArgumentException: Comparison method violates its general contract
! If Marina read documentation in the evenings, she would know that in this case it is best to use the Collections.shuffle()
method.Collections.shuffle()
method.ArrayList
of 10 lines is passed to it? Predicate<String> equalsAny(List<String> list) { Predicate<String> p = s -> false; for (String s : list) { p = p.or(s::contains); } return p; }
p = p.or(s::contains);
p.or()
, and the second to create the predicate s::contains
. The latter cannot be cached, since it captures the variable s
in the context. Multiplying by the number of iterations, we get 20 objects. But also a hidden Iterator
can be created if the JIT does not optimize it. “20 or even 21 objects, if not lucky, are sinful,” Alina thought.or
+ 10 predicates contains
+ 1 Iterator
depending on JIT optimizations. AtomicLong max = new AtomicLong(); void addValue(long v) { if (v > max.get()) { max.set(v); } }
AtomicLong
does not make the program thread-safe. For this there is an atomic operation AtomicLong.compareAndSwap
. And starting with Java 8, it’s not at all necessary to write the CAS loop yourself, because the remarkable atomic method accumulateAndGet
. And here it is convenient to use just it: void addValue(long v) { max.accumulateAndGet(v, Math::max); }
Source: https://habr.com/ru/post/427337/
All Articles