Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ch.claude_martin.utils;
- import java.util.Arrays;
- import java.util.PrimitiveIterator.OfInt;
- import java.util.Spliterator;
- import java.util.Spliterators;
- import java.util.stream.IntStream;
- import java.util.stream.StreamSupport;
- public class ArrayMerge {
- public static void main(String[] args) {
- mergeArrays(ints(-1, 0, 1, 2, 3), ints(4, 4, 5, 5), ints(5, 6, 7, 8), ints(-4, 8, 12)).forEach(i -> {
- System.out.print(i);
- System.out.print(',');
- });
- System.out.println();
- }
- static int[] ints(int... input) {
- return input;
- }
- /** Merges multiple sorted arrays of integers.
- * The input is not altered by this method. */
- public static IntStream mergeArrays(int[]... input) {
- final int k = input.length;
- final long totalSize = Arrays.stream(input).mapToLong(a -> a.length).sum();
- if (totalSize == 0)
- return IntStream.empty();
- // Array of the current indices of the next values to be returned:
- final int[] indices = new int[k];
- // Copy so that empty arrays can be replaced by null:
- final int[][] copy = Arrays.copyOf(input, k);
- final OfInt ofInt = new OfInt() {
- int nonNull = k;
- @Override
- public boolean hasNext() {
- return this.nonNull > 0;
- }
- @Override
- public int nextInt() {
- int minValue = Integer.MAX_VALUE;
- int minIndex = -1;
- for (int j = 0; j < k; j++) {
- int[] array = copy[j];
- if (null == array)
- continue;
- final int value = array[indices[j]];
- if (value < minValue) {
- minValue = value;
- minIndex = j;
- }
- }
- if (++indices[minIndex] == copy[minIndex].length) {
- copy[minIndex] = null;
- this.nonNull--;
- }
- return minValue;
- }
- };
- var spliterator = Spliterators.spliterator(ofInt, totalSize,
- Spliterator.SIZED | Spliterator.ORDERED | Spliterator.SORTED | Spliterator.IMMUTABLE);
- return StreamSupport.intStream(spliterator, false);
- }
- /** Same method using ConcurrentSkipListMap, which is much faster. */
- static IntStream parallelMergeArrays(int[]... input) {
- var multiset = new ConcurrentSkipListMap<Integer, Integer>();
- final long totalSize = Arrays.stream(input).mapToLong(a -> a.length).sum();
- Arrays.stream(input).parallel().forEach(array -> {
- for (var i : array)
- multiset.compute(i, (value, occurrences) -> null == occurrences ? 1 : occurrences + 1);
- });
- final OfInt ofInt = new OfInt() {
- int returned = 0;
- @Override
- public boolean hasNext() {
- return this.returned < totalSize;
- }
- @Override
- public int nextInt() {
- final var first = multiset.firstEntry();
- final var key = first.getKey();
- final var occurrences = first.getValue();
- if (occurrences == 1) {
- multiset.remove(key);
- } else {
- //first.setValue(occurrences - 1);
- multiset.put(key, occurrences - 1);
- }
- this.returned++;
- return key;
- }
- };
- var spliterator = Spliterators.spliterator(ofInt, totalSize,
- Spliterator.SIZED | Spliterator.ORDERED | Spliterator.SORTED | Spliterator.IMMUTABLE);
- return StreamSupport.intStream(spliterator, false);
- }
- }
Advertisement