Returns the ordinal of the first element in the list which is equal to a previous element in the list. For example, firstDuplicate(Arrays.asList("a", "b", "c", "b", "a")) returns 3, the ordinal of the 2nd "b". @param list List @return Ordinal of first duplicate, or -1 if not found
(List<E> list)
| 2272 | * @return Ordinal of first duplicate, or -1 if not found |
| 2273 | */ |
| 2274 | public static <E> int firstDuplicate(List<E> list) { |
| 2275 | final int size = list.size(); |
| 2276 | if (size < 2) { |
| 2277 | // Lists of size 0 and 1 are always distinct. |
| 2278 | return -1; |
| 2279 | } |
| 2280 | if (size < QUICK_DISTINCT) { |
| 2281 | // For smaller lists, avoid the overhead of creating a set. Threshold |
| 2282 | // determined empirically using UtilTest.testIsDistinctBenchmark. |
| 2283 | for (int i = 1; i < size; i++) { |
| 2284 | E e = list.get(i); |
| 2285 | for (int j = i - 1; j >= 0; j--) { |
| 2286 | E e1 = list.get(j); |
| 2287 | if (Objects.equals(e, e1)) { |
| 2288 | return i; |
| 2289 | } |
| 2290 | } |
| 2291 | } |
| 2292 | return -1; |
| 2293 | } |
| 2294 | // we use HashMap here, because it is more efficient than HashSet. |
| 2295 | final Map<E, Object> set = new HashMap<>(size); |
| 2296 | for (E e : list) { |
| 2297 | if (set.put(e, "") != null) { |
| 2298 | return set.size(); |
| 2299 | } |
| 2300 | } |
| 2301 | return -1; |
| 2302 | } |
| 2303 | |
| 2304 | /** |
| 2305 | * Returns whether the elements of {@code list} are definitely distinct |