Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
CollectionUtils |
|
| 5.0;5 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, software | |
13 | * distributed under the License is distributed on an "AS IS" BASIS, | |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | * See the License for the specific language governing permissions and | |
16 | * limitations under the License. | |
17 | */ | |
18 | ||
19 | package org.apache.giraph.utils; | |
20 | ||
21 | import com.google.common.collect.Iterables; | |
22 | import java.util.Collection; | |
23 | import java.util.Iterator; | |
24 | import java.util.concurrent.ConcurrentMap; | |
25 | import org.apache.log4j.Logger; | |
26 | ||
27 | /** Helper methods for Collections */ | |
28 | public class CollectionUtils { | |
29 | /** Class logger */ | |
30 | 0 | private static final Logger LOG = Logger.getLogger(CollectionUtils.class); |
31 | ||
32 | /** Do not instantiate. */ | |
33 | 0 | private CollectionUtils() { } |
34 | ||
35 | /** | |
36 | * If map already has a value associated with the key it adds values to that | |
37 | * value, otherwise it will put values to the map. Do not reuse values. | |
38 | * | |
39 | * @param key Key under which we are adding values | |
40 | * @param values Values we want to add | |
41 | * @param map Map which we are adding values to | |
42 | * @param <K> Key | |
43 | * @param <V> Value | |
44 | * @param <C> Collection | |
45 | * @return New value associated with the key | |
46 | */ | |
47 | public static <K, V, C extends Collection<V>> C addConcurrent(K key, | |
48 | C values, ConcurrentMap<K, C> map) { | |
49 | 0 | C currentValues = map.get(key); |
50 | 0 | if (currentValues == null) { |
51 | 0 | currentValues = map.putIfAbsent(key, values); |
52 | 0 | if (currentValues == null) { |
53 | 0 | return values; |
54 | } | |
55 | } | |
56 | 0 | synchronized (currentValues) { |
57 | 0 | currentValues.addAll(values); |
58 | 0 | } |
59 | 0 | return currentValues; |
60 | } | |
61 | ||
62 | /** | |
63 | * Helper method to check if iterables are equal. Supports the case | |
64 | * where the iterable next() returns a reused object. We do assume that | |
65 | * iterator() produces the objects in the same order across repeated calls, | |
66 | * if the object doesn't change. This is very expensive (n^2) and should | |
67 | * be used for testing only. | |
68 | * | |
69 | * @param first First iterable | |
70 | * @param second Second iterable | |
71 | * @param <T> Type to compare | |
72 | * @return True if equal, false otherwise | |
73 | */ | |
74 | public static <T> boolean isEqual(Iterable<T> first, Iterable<T> second) { | |
75 | // Relies on elements from the iterator arriving in the same order. | |
76 | // For every element in first, check elements on the second iterable by | |
77 | // marking the ones seen that have been found. Then ensure that all | |
78 | // the elements of the second have been seen as well. | |
79 | 0 | int firstSize = Iterables.size(first); |
80 | 0 | int secondSize = Iterables.size(second); |
81 | 0 | boolean[] usedSecondArray = new boolean[secondSize]; |
82 | 0 | Iterator<T> firstIterator = first.iterator(); |
83 | 0 | while (firstIterator.hasNext()) { |
84 | 0 | T firstValue = firstIterator.next(); |
85 | 0 | boolean foundFirstValue = false; |
86 | 0 | Iterator<T> secondIterator = second.iterator(); |
87 | 0 | for (int i = 0; i < usedSecondArray.length; ++i) { |
88 | 0 | T secondValue = secondIterator.next(); |
89 | 0 | if (!usedSecondArray[i]) { |
90 | 0 | if (firstValue.equals(secondValue)) { |
91 | 0 | usedSecondArray[i] = true; |
92 | 0 | foundFirstValue = true; |
93 | 0 | break; |
94 | } | |
95 | } | |
96 | } | |
97 | ||
98 | 0 | if (!foundFirstValue) { |
99 | 0 | LOG.error("isEqual: Couldn't find element from first (" + firstValue + |
100 | ") in second " + second + "(size=" + secondSize + ")"); | |
101 | 0 | return false; |
102 | } | |
103 | 0 | } |
104 | ||
105 | 0 | Iterator<T> secondIterator = second.iterator(); |
106 | 0 | for (int i = 0; i < usedSecondArray.length; ++i) { |
107 | 0 | T secondValue = secondIterator.next(); |
108 | 0 | if (!usedSecondArray[i]) { |
109 | 0 | LOG.error("isEqual: Element " + secondValue + " (index " + i + |
110 | ") in second " + second + "(size=" + secondSize + | |
111 | ") not found in " + first + " (size=" + firstSize + ")"); | |
112 | 0 | return false; |
113 | } | |
114 | } | |
115 | ||
116 | 0 | return true; |
117 | } | |
118 | } |