Merge two text input files, each line of files one by one. See Example

I tried to solve the problem using java 8, which I already solved using a simple loop. However, I have no idea how to do this. The problem is this:

File1 : 
1,sdfasfsf
2,sdfhfghrt
3,hdfxcgyjs

File2 : 
10,xhgdfgxgf
11,hcvcnhfjh
12,sdfgasasdfa
13,ghdhtfhdsdf

The output should look like

1,sdfasfsf
10,xhgdfgxgf
2,sdfhfghrt
11,hcvcnhfjh
3,hdfxcgyjs
12,sdfgasasdfa
13,ghdhtfhdsdf

I already have this job basically,

The main logic:

List<String> left  = readFile(lhs);
List<String> right = readFile(rhs);
int leftSize = left.size();
int rightSize = right.size();
int size =  leftSize > rightSize? leftSize : right.size();
for (int i = 0; i < size; i++) {
    if(i < leftSize) {
        merged.add(left.get(i));
    }
    if(i < rightSize) {
        merged.add(right.get(i));
    }
}
  • MergeInputs.java
  • Unittest
  • The input files are in the src / test / resources / com / linux / test / merge / file of the list of the same repo (only two links are allowed)

However, I boasted that I could easily do this using threads, and now I'm not sure that this can even be done.

Help is really appreciated.

+4
source share
2 answers

, :

int leftSize = left.size(), rightSize = right.size(), min = Math.min(leftSize, rightSize);
List<String> merged = new ArrayList<>(leftSize+rightSize);
for(int i = 0; i < min; i++) {
    merged.add(left.get(i));
    merged.add(right.get(i));
}
if(leftSize!=rightSize) {
    merged.addAll(
        (leftSize<rightSize? right: left).subList(min, Math.max(leftSize, rightSize)));
}

:

int leftSize = left.size(), rightSize = right.size(), min = Math.min(leftSize, rightSize);

List<String> merged=IntStream.range(0, min)
        .mapToObj(i -> Stream.of(left.get(i), right.get(i)))
        .flatMap(Function.identity())
        .collect(Collectors.toCollection(ArrayList::new));
if(leftSize!=rightSize) {
    merged.addAll(
        (leftSize<rightSize? right: left).subList(min, Math.max(leftSize, rightSize)));
}

, . - .

(, , ).

+3

:

int leftSize = left.size();
int rightSize = right.size();
int minSize = Math.min(leftSize,rightSize);

for (int i = 0; i < minSize; i++) {
    merged.add(left.get(i));
    merged.add(right.get(i));
}

// adding remaining elements
merged.addAll(
        minSize < leftSize ? left.subList(minSize, leftSize)
                           : right.subList(minSize, rightSize)
);

- Iterator, :

toggle(left, right).forEachRemaining(merged::add);

//OR using stream instead
List<String> merged = Stream.generate(toggle(left, right)::next)
                            .limit(left.size() + right.size())
                            .collect(Collectors.toList());

toggle, :

<T> Iterator<? extends T> toggle(List<T> left, List<T> right) {
    return new Iterator<T>() {
        private final int RIGHT = 1;
        private final int LEFT = 0;
        int cursor = -1;
        Iterator<T>[] pair = arrayOf(left.iterator(), right.iterator());

        @SafeVarargs
        private final Iterator<T>[] arrayOf(Iterator<T>... iterators) {
            return iterators;
        }

        @Override
        public boolean hasNext() {
            for (Iterator<T> each : pair) {
                if (each.hasNext()) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public T next() {
            return pair[cursor = next(cursor)].next();
        }

        private int next(int cursor) {
            cursor=pair[LEFT].hasNext()?pair[RIGHT].hasNext()?cursor: RIGHT:LEFT;
            return (cursor + 1) % pair.length;
        }
    };
}
+1

Source: https://habr.com/ru/post/1680116/


All Articles