List<String>
statistics of all the location of each element appears.
For example, given List: ["a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g"]
, it should return:
a : [0] b : [1, 2] c : [3, 4, 5] d : [6, 7, 8] f : [9, 10] g : [11]
Obviously, we are very suitable Map
to accomplish these things:
public static Map<String, List<Integer>> getElementPositions(List<String> list) {
Map<String, List<Integer>> positionsMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
List<Integer> positions = positionsMap.get(str);
if (positions == null) { // 如果 positionsMap 还不存在 str 这个键及其对应的 List<Integer>
positions = new ArrayList<>(1);
positionsMap.put(str, positions); // 将 str 及其对应的 positions 放入 positionsMap
}
positions.add(i); // 将索引加入 str 相关联的 List<Integer> 中
}
return positionsMap;
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
System.out.println("使用 Java8 之前的 API:");
Map<String, List<Integer>> elementPositions = getElementPositions(list);
System.out.println(elementPositions);
}
复制代码
operation result:
Java8
, The Map<K, V>
interface adds a new method putIfAbsent(K key, V value)
, function is: If the current Map
key is not present key
or the key
associated value null
, then the execution put(key, value)
; otherwise, they will not perform put operations. This method is equivalent to the following code:
(Digression: putIfAbsent
methods and put
methods as returns before the method invocation parameters key
associated value
)
Using putIfAbsent
modified getElementPositions
methods:
public static Map<String, List<Integer>> getElementPositions(List<String> list) {
Map<String, List<Integer>> positionsMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
positionsMap.putIfAbsent(str, new ArrayList<>(1)); // 如果 positionsMap 不存在键 str 或者 str 关联的 List<Integer> 为 null,那么就会进行 put;否则不执行 put
positionsMap.get(str).add(i);
}
return positionsMap;
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
System.out.println("使用 putIfAbsent:");
Map<String, List<Integer>> elementPositions = getElementPositions(list);
System.out.println(elementPositions);
}
复制代码
operation result:
It can be seen using the putIfAbsent
following getElementPositions
simple point, that it could be more concise?
Check Map
the interface method can be found in JDK1.8
time, we add the following two methods:
Check compute
method of API
documents, you can find compute
a method with the following code is equivalent to
V oldValue = map.get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (oldValue != null ) {
if (newValue != null)
map.put(key, newValue);
else
map.remove(key);
} else { // 即 原来的 key 不存在 Map 中或该 key 关联的 value 为 null
if (newValue != null)
map.put(key, newValue);
else
return null;
}
复制代码
compute
The original method and put
the difference method is:
put(K key, V value)
Method, if key
the Map
does not exist, then added directly; if it already exists, then the use of the new value
replacing the old value
;
The compute(K key, BiFunction remappingFunction)
method can be calculated by a new BiFunction value
, BiFunction
the old parameters key
and value
return to calculate a new value
- and put
different methods, compute
the method returns would be the latest and key
associated value
, instead of the old value
. It is possible to use compute
a method rewritten getElementPositions
as follows:
public static Map<String, List<Integer>> getElementPositions(List<String> list) {
Map<String, List<Integer>> positionsMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
positionsMap.compute(list.get(i), (k, v) -> v == null ? new ArrayList<>(1) : v).add(i);
}
return positionsMap;
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
System.out.println("使用 compute:");
Map<String, List<Integer>> elementPositions = getElementPositions(list);
System.out.println(elementPositions);
}
复制代码
(k, v) -> v == null ? new ArrayList<>(1) : v
That is, if the current value null
, then the BiFunction
return value new ArrayList<>(1)
; if not null
, then the return value is itself. And because the compute
method returns a new value
- and at this time is the list.get(i)
(key) associated with ArrayList
- so we can call it a direct add
approach.
operation result:
Great - but also more concise yet? Let us look at computeIfAbsent
methods: computeIfAbsent
and compute
relationship, similar to putIfAbsent
and put
relationships: computeIfAbsent
in key
absence Map
or with key
associated value
is null
only when the function is performed by computing a new value
operation, and otherwise does; computeIfAbsent
the return value is the key
latest associated a value
. Its default implementation is as follows:
And compute
different, computeIfAbsent
acceptable operation is a function Function
and not BiFunction
- this is well understood, computeIfAbsent
only ke
y is not Map
, or with the key
associated value
to null
only perform the function operation, then clearly this time and key
related value
to null
, so computeIfAbsent
only accept Function
can be used as parameters - which Function
can be used key
as a new parameter calculation value
. Use computeIfAbsent
rewrite getElementPositions
:
public static Map<String, List<Integer>> getElementPositions(List<String> list) {
Map<String, List<Integer>> positionsMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
positionsMap.computeIfAbsent(list.get(i), k -> new ArrayList<>(1)).add(i);
}
return positionsMap;
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
System.out.println("使用 computeIfAbsent:");
Map<String, List<Integer>> elementPositions = getElementPositions(list);
System.out.println(elementPositions);
}
复制代码
operation result:
In fact, as used herein, putIfAbsent
was present when the issue positionsMap.putIfAbsent(str, new ArrayList<>(1))
; this code when each call will have a temporary ArrayList
- when traversed List<String>
when large, this may bring some negative effects; contrast compute
and computeIfAbsent
benefits that they accept the parameters for the function, it will only be calculated when necessary to use a new function value
. In the case of this paper, similar needs, you applicability and simplicity, it computeIfAbsent
is superior compute
. In JDK1.8
the API documentation, also said in the need to generate a similar Map<K, Collection<V>>
time of construction, computeIfAbsent
it is suitable for this situation:
That compute
method is suitable for what happens then? Seen from the preceding description, compute
the method is more suitable for updating key
the associated value
time, the new value of the old value depends on the situation - such as a count List<String>
the number of times each element appears:
public static Map<String, Integer> getElementCounts(List<String> list) {
Map<String, Integer> countsMap = new HashMap<>();
list.forEach(str -> countsMap.compute(str, (k, v) -> v == null ? 1 : v + 1)); // 此时:新值 = 旧值 + 1
return countsMap;
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
System.out.println("使用 compute 计算元素出现的次数:");
Map<String, Integer> counts = getElementCounts(list);
System.out.println(counts);
}
复制代码
operation result:
Java8
Is also Map
added some other new methods to facilitate encoding, interested readers continue to explore.
Original Address: segmentfault.com/a/119000000...
recommend
Manufacturers written content collection (with detailed analytical) continuously updated in ....
ProcessOn aggregation platform is an online mapping tool -
The end of the sentence
Welcome attention to personal micro-channel public number: Coder programming welcome attention Coder programming public numbers, the main share data structures and algorithms, Java-related knowledge, the framework of knowledge and principle, Spring family bucket, micro-services project combat, DevOps practices of the road, one day Internet giant pen articles or interview questions and PMP project management knowledge. More exciting content is on the way - built a qq group: 315 211 365, we welcome into the group exchange study together. Thank you! Can also be introduced to the side of a friend in need.
Articles included to Github: github.com/CoderMerlin... Gitee: gitee.com/573059382/c... welcome attention and star ~