Collectors. Analysis of tocurrentmap source code

As a bully who is either on the road or on the road
Ben Wang dismantled collectors today toConcurrentMap
Look what's going on inside him
Well, for those who don't know about functional programming, I recommend watching the second edition of java practice
To understand this blog, you need a certain foundation of functional programming. At least you have to understand what behavior parameterization is
For those who don't know the subtype rules of generics and unlimited wildcard types, the following blogs are recommended
https://www.cnblogs.com/jian0110/p/10690483.html

1, Good opening

Behavior parameterization is a software development model that can help you deal with frequently changing requirements.
Ben Wang gives a simple example that is easy to understand
1. We define an object, earth as a parameter object; Execution - rotation
2. We define an object, the sun - as a parameter object; Execute - glow and heat
3. We define an object, BloomFilter - "as a parameter object; Execute current limiting operation
4. We define another object, MyLock - "as a parameter object; Execute lock upgrade, spin upgrade if successful / retry if failed
5. We define an object, string array - "as a parameter object; Returns a non empty string in the array

Is there a method that can be used in all the above cases?
JDK1. I couldn't do it before, jkd1 It's OK after 8
Think about it. We can write a method to pass in the object + behavior as a parameter, eg:

 public void used( I am an object,Any type is OK Object object,
 I'm an act, anything Active<T> active ) {
              So here:  1.earth + spin
                        2.sun + Luminous heating
                        3.BloomFilter + Current limiting
                        4.MyLock + Lock upgrade, spin - Upgrade if successful/Retry if failed
                        5.String array + Returns a non empty string in the array
        }

This is called behavior parameterization
Now write a simple example to define a used method, so that she can perform different operations on the same string array. Let's take a look at her specific code implementation

In the following code, we pass "object and concrete behavior operation" as parameters into the method used (object, behavior)

1. We first define a functional interface, returnboolean < T >, which can accept an object and return the object after filtering. The purpose of defining her is to correspond to the parsing of Lambda expression
If Java util. For function interfaces with the same functions under function, you should not define them separately. This is just for example (in fact, it is equivalent to predict < T)

@FunctionalInterface
public interface ReturnBoolean<T> {
    boolean active(T t);
}

This is equivalent to the above used() method, List - > object, returnboolean < T > behavior (operation performed)

    public <T> List<T> filter(List<T> list ,ReturnBoolean<T> r) {
        List<T> results = new ArrayList<>();
        for (T t : list) {
            if (r.active(t)) {
                results.add(t);
            }
        }
        return results;

    }

When in use, the specific behavior is passed in:

ReturnBoolean<String> r = (String i) -> !i.isEmpty();// String array is an object behavior: filter non empty strings in the array
    ReturnBoolean<String> r1 = (String i) -> i.contains("a");//String array is object behavior: filter the string containing "a" in the array
    ReturnBoolean<Integer> i1 = (Integer i) -> i > 0;//In Integer array, behavior: filter data greater than 0
    ReturnBoolean<Car> u1 = (Car car) -> car.canRun();//List < car >, behavior: screen cars that can run
    List<String> strings = Arrays.asList("ss","sdfka","","abc");
    List<String> str = used(strings,r);

2, Collectors Tocurrentmap source code analysis

There should be many words here
ConcurrentHashMap is in jdk1 8. Great changes have been made. The underlying structure has changed to array + linked list + red black tree,
The internal Node is also changed from an Entry Node to a Node node,
Unlike HashTable, which locks all methods with synchonized locks, it only locks related node nodes, which is unclear and may not be understood later,
According to Poisson distribution, when the default load factor is 0.75, the probability of 8 elements in a single Hash Cao is less than one in a million, so when the number of elements > = 8, linked list - > red black tree<= 6:00, red black tree - > linked list; No change at 7
Well, that's almost it. Let's get to the point

public ConcurrentHashMap<String,Long> getList() 
{
            return LongStream.rangeClosed(1,10)
                    .boxed()
                    .collect(Collectors.toConcurrentMap(i -> "a", identity(),
            (o1,o2) -> o1,ConcurrentHashMap::new));
        }

We go to collectors Java, find her

 public static <T, K, U, M extends ConcurrentMap<K, U>>
    Collector<T, ?, M> toConcurrentMap
    (
    Function<? super T, ? extends K> keyMapper,
    Function<? super T, ? extends U> valueMapper,
    BinaryOperator<U> mergeFunction,
    Supplier<M> mapSupplier
   ) {
  BiConsumer<M, T> accumulator
  = (map, element) -> map.merge(keyMapper.apply(element),
	valueMapper.apply(element), mergeFunction);
  return new CollectorImpl<>(mapSupplier, accumulator,               mapMerger(mergeFunction), CH_CONCURRENT_ID);
    }

It's actually very simple:
Function<? super T, ? Extensions k > keymapper to map keys
Function<? super T, ? Extensions U > valuemapper to map values
Binaryoperator < U > mergefunction is a dual operation, (o1,o2) - > O1,

Ben Wang is not at ease: so let's talk about it, otherwise some little friends are really listening to the book of heaven
public int getNewObject(int o1,int o2){
return o1 > o2 ? o1 : o2;
}
->
Pass in two parameters of the same type and return a return value (also of the same type)
Supplier < m > mapsupplier provides specific implementation classes for implementing ConcurrentMap
Enter map merge(keyMapper.apply(element), valueMapper. Apply (element), mergefunction)

 @Override
    default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);//Get the old value value through the passed in key
        for (;;) {
        //If you can get value from the original Map, think of it as an old value,
            if (oldValue != null) {
            //When there is an old value, compare it with our new value
            //If not, return a new value
           V newValue = remappingFunction.apply(oldValue, value);
                //If a new value is returned, call the replace method in ConcurrentHashMap to replace it. See, the node node is replaced!
                /*
        public boolean replace(K key, V oldValue, V newValue) {
        if (key == null || oldValue == null || newValue == null)
            throw new NullPointerException();
        return replaceNode(key, newValue, oldValue) != null;
    }
    */
              
                if (newValue != null) {
                    if (replace(key, oldValue, newValue))
                        return newValue;
                        //Returns NULL if there is no new value or the new value is null
                } else if (remove(key, oldValue)) {
                    return null;
                }
                oldValue = get(key);
            } else {
                if ((oldValue = putIfAbsent(key, value)) == null) {
                    return value;
                }
            }
        }
    }

Today, let's get to know her implementation a little. When we have time later, we'll continue to dismantle......

Tags: Java Lambda Functional Programming

Posted by charleshill on Thu, 12 May 2022 19:37:57 +0300