private static List<String> mergeListsUsingRef(List<String> listRefRaw,List<String> listA,List<String> listB) {
List<String> listRef = uniques(listRefRaw);
Set<String> common = new HashSet<>();
common.addAll(listA);
common.addAll(listB);
List<String> result = new ArrayList<>(listRef);
result.retainAll(common);
return result;
}
如果参考列表与两个列表相比都很大:
return listRef.stream()
.filter(common::contains)
.collect(Collectors.toList());
这将保留参考列表的顺序。这里的主要问题是
listA和listB都没有设置,所以不可能进行快速的包含检查。
private static List<String> uniques(List<String> listRefRaw) {
Set<String> uniqueValues = new HashSet<>();
return listRefRaw.stream()
.filter(s -> !uniqueValues.contains(s))
.peek(uniqueValues::add)
.collect(Collectors.toList());
}
很遗憾,Stream.distinct()
在无序集合中不稳定,
所以上面应该做。
,
我认为此解决方案将起作用-保留列表的顺序,并为上面显示的所有示例提供正确答案。通过将引用列表保留为索引的hashMap,它可以快速查询任意两个整数(如果一个整数可以在引用之前出现在另一个整数之前)。我在主机上添加了打印输出以进行测试。
public class ListMergeByRef {
public Map<Integer,List<Integer>> refMap = new HashMap<Integer,List<Integer>>();
public ListMergeByRef(List<Integer> reference) {
int elementIndex = 0;
for (Integer element:reference) {
List<Integer> refListPerElement = refMap.get(element);
if (refListPerElement == null) {
refListPerElement = new ArrayList<Integer>();
}
refListPerElement.add(elementIndex);
elementIndex++;
refMap.put(element,refListPerElement);
}
}
public List<Integer> mergeLists (List<Integer> first,List<Integer> second) {
int firstIndex = 0;
int secondIndex = 0;
List<Integer> merged = new ArrayList<Integer>();
while (firstIndex < first.size() || secondIndex < second.size()) {
if (firstIndex == first.size()) {
merged.addAll(second.subList(secondIndex,second.size()));
return merged;
} else if (secondIndex == second.size()) {
merged.addAll(first.subList(firstIndex,first.size()));
return merged;
}
if (first.get(firstIndex).equals(second.get(secondIndex))){
merged.add(first.get(firstIndex));
firstIndex++;
secondIndex++;
}
else if (isElementAllowedBeforeOther(first.get(firstIndex),second.get(secondIndex))) {
merged.add(first.get(firstIndex));
firstIndex++;
} else {
merged.add(second.get(secondIndex));
secondIndex++;
}
}
return merged;
}
public boolean isElementAllowedBeforeOther(Integer firstElement,Integer secondElement) {
List<Integer> firstElementIndexes = refMap.get(firstElement);
List<Integer> secondElementIndexes = refMap.get(secondElement);
if (firstElementIndexes == null || firstElementIndexes.isEmpty()) return false;
if (secondElementIndexes == null || secondElementIndexes.isEmpty()) return true;
if (firstElementIndexes.get(0) < secondElementIndexes.get(secondElementIndexes.size()-1)) return true;
return false;
}
public static void main(String[] args) {
List<Integer> ref = Arrays.asList(new Integer[] {1,2,3,4,5,6,7,8});
List<Integer> first = Arrays.asList(new Integer[] {2,7});
List<Integer> second = Arrays.asList(new Integer[] {4,8});
ListMergeByRef merger = new ListMergeByRef(ref);
List<Integer> mergedList = merger.mergeLists(first,second);
for (Integer element: mergedList) {
System.out.print(element+" ");
}
System.out.println();
}
,
前两个测试失败,因为您期望的列表缺少第二个4。要合并的列表中存在两个4。
无论如何,我只是遍历了ref并从试图合并的列表中删除了所有匹配项。
public static <E extends Comparable<E>>List<E> merge(List<E> refList,List<E>... lists) {
List<E> result = new ArrayList<E>();
Iterator<E> ref = refList.iterator();
boolean found = false;
while (ref.hasNext()) {
E curr = ref.next();
found = false; // Reset
for (List<E> list : lists) {
if (found) continue; // If already found,skip the next list
for (Iterator<E>it = list.iterator(); !found && it.hasNext();) {
E term = it.next();
boolean equal = term.equals(curr);
if (equal) {
result.add(term);
list.remove(term);
found = true;
}
}
}
}
return result;
}
完整示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ListReferenceJoiner {
public static final boolean DEBUG = true;
public static void main(String[] args) {
System.out.printf("Equal? %b%n",test1());
System.out.println("===================");
System.out.printf("Equal? %b%n",test2());
System.out.println("===================");
System.out.printf("Equal? %b%n",test3());
System.out.println("===================");
System.out.printf("Equal? %b%n",test4());
}
private static boolean test1() {
List<Integer> refList = asArrayList(1,8);
List<Integer> listA = asArrayList(2,7);
List<Integer> listB = asArrayList(4,8);
List<Integer> expected = asArrayList(2,8);
return testRunner(refList,listA,listB,expected); // 2,8
}
private static boolean test2() {
List<Integer> refList = asArrayList(1,8
}
private static boolean test3() {
List<Integer> refList = asArrayList(1,7);
List<Integer> listB = asArrayList(6,8
}
private static boolean test4() {
List<Integer> refList = asArrayList(1,8
}
private static boolean testRunner(List<Integer> ref,List<Integer> listA,List<Integer> listB,List<Integer> expected) {
if (DEBUG) {
System.out.printf("Expecting: %s%n",expected);
}
List<Integer> actual = merge(ref,listB); // 2,8
if (DEBUG) {
System.out.printf("Actual: %s%n",actual);
}
return expected.equals(actual);
}
@SuppressWarnings("unchecked")
public static <E extends Comparable<E>>List<E> merge(List<E> refList,List<E>... lists) {
List<E> result = new ArrayList<E>();
Iterator<E> ref = refList.iterator();
boolean found = false;
while (ref.hasNext()) {
if (DEBUG) {
printLists(lists);
}
E curr = ref.next();
found = false; // Reset
for (List<E> list : lists) {
if (found) continue; // If already found,skip the next list
for (Iterator<E>it = list.iterator(); !found && it.hasNext();) {
E term = it.next();
boolean equal = term.equals(curr);
if (equal) {
if (DEBUG) {
System.out.printf("Found '%s'%n",term);
}
result.add(term);
list.remove(term);
found = true;
}
}
}
if (DEBUG && !found) {
System.out.printf("Could not find '%s'%n",curr);
}
}
return result;
}
private static <E> void printLists(List<E>... lists) {
for (ListIterator< List<E>>it = Arrays.asList(lists).listIterator(); it.hasNext();) {
printList(it.next(),getCharForNumber(it.nextIndex()));
}
}
private static <E> void printList(List<E> list,String label) {
System.out.printf("%s: ",label);
for (Iterator< E>it = list.iterator(); it.hasNext();) {
System.out.print(it.next());
if (it.hasNext()) {
System.out.print(" | ");
}
}
System.out.print(System.lineSeparator());
}
@SuppressWarnings("unchecked")
private static <E> List<E> asArrayList(E... values) {
return new ArrayList<E>(Arrays.asList(values));
}
protected static String getCharForNumber(int i) {
return i > 0 && i < 27 ? String.valueOf((char) (i + 64)) : null;
}
}
这是莫里斯·佩里(Maurice Perry)的回应版本,但仍然无法保留顺序。
private static <E> List<E> merge(final List<E> listRef,final List<E>... lists) {
final List<E> res = new ArrayList<E>();
final List<List<E>> copies = Arrays.stream(lists).map(ArrayList::new).collect(Collectors.toList());
for (E ref : listRef) {
boolean found = false;
for (Iterator<List<E>> it = copies.iterator(); !found && it.hasNext();) {
if (it.next().remove(ref)) {
res.add(ref);
found = true;
}
}
if (found) {
continue;
}
}
return res;
}
示例输出
Testing: [2,8]
A: 2 | 3 | 5 | 4 | 7
B: 4 | 7 | 8
Could not find '1'
A: 2 | 3 | 5 | 4 | 7
B: 4 | 7 | 8
Found '2'
A: 3 | 5 | 4 | 7
B: 4 | 7 | 8
Found '3'
A: 5 | 4 | 7
B: 4 | 7 | 8
Found '4'
A: 5 | 7
B: 4 | 7 | 8
Found '5'
A: 7
B: 4 | 7 | 8
Could not find '6'
A: 7
B: 4 | 7 | 8
Found '4'
A: 7
B: 7 | 8
Found '7'
A:
B: 7 | 8
Found '8'
Actual: [2,8]
Equal? false
===================
Testing: [2,8]
A: 2 | 3 | 4 | 5 | 7
B: 4 | 7 | 8
Could not find '1'
A: 2 | 3 | 4 | 5 | 7
B: 4 | 7 | 8
Found '2'
A: 3 | 4 | 5 | 7
B: 4 | 7 | 8
Found '3'
A: 4 | 5 | 7
B: 4 | 7 | 8
Found '4'
A: 5 | 7
B: 4 | 7 | 8
Found '5'
A: 7
B: 4 | 7 | 8
Could not find '6'
A: 7
B: 4 | 7 | 8
Found '4'
A: 7
B: 7 | 8
Found '7'
A:
B: 7 | 8
Found '8'
Actual: [2,8]
A: 2 | 3 | 4 | 5 | 7
B: 6 | 4 | 7 | 8
Could not find '1'
A: 2 | 3 | 4 | 5 | 7
B: 6 | 4 | 7 | 8
Found '2'
A: 3 | 4 | 5 | 7
B: 6 | 4 | 7 | 8
Found '3'
A: 4 | 5 | 7
B: 6 | 4 | 7 | 8
Found '4'
A: 5 | 7
B: 6 | 4 | 7 | 8
Found '5'
A: 7
B: 6 | 4 | 7 | 8
Found '6'
A: 7
B: 4 | 7 | 8
Found '4'
A: 7
B: 7 | 8
Found '7'
A:
B: 7 | 8
Found '8'
Actual: [2,8]
Equal? true
===================
Testing: [2,8]
A: 2 | 3 | 4 | 5 | 7
B: 6 | 7 | 8
Could not find '1'
A: 2 | 3 | 4 | 5 | 7
B: 6 | 7 | 8
Found '2'
A: 3 | 4 | 5 | 7
B: 6 | 7 | 8
Found '3'
A: 4 | 5 | 7
B: 6 | 7 | 8
Found '4'
A: 5 | 7
B: 6 | 7 | 8
Found '5'
A: 7
B: 6 | 7 | 8
Found '6'
A: 7
B: 7 | 8
Could not find '4'
A: 7
B: 7 | 8
Found '7'
A:
B: 7 | 8
Found '8'
Actual: [2,8]
Equal? true
,
您的代码正常工作!
但是有2个问题:
-
您的逻辑不需要null检查。
由于equals(null)
是required才能返回false
,因此可以安全地将if (a != null && ref.equals(a))
缩小为if (ref.equals(a))
-
您对EX 1的期望不正确。
这些值匹配如下:
ref: "1","2","3","4","5","6","7","8"
---------------------------------------------------
A: "2","7"
B: "4","8"
===================================================
result: "2","8"
但是你在期待
"2","8"
如您所见,您也应该期待第一个 4 。
本文链接:https://www.f2er.com/3102081.html