Java:Interleave两个基于整数的arraylists – >好方法?

家庭作业:寻找更好的策略,或者接近而不是完整的代码。

我在两个条件下有两个整数数组列表:

  1. 第一个列表大于第二个列表
  2. 第二个列表大于第一个列表

我的目标是在两种条件下将list2的元素交织到list1中。 我已经创建了一个方法来做到这一点,但我觉得我可以做得更好。

这是条件1的预期结果。请注意,在list2的元素用完之后,我们将list1的元素保留在原位:

list1: [10, 20, 30, 40, 50, 60, 70] list2: [4, 5, 6, 7] Combined: [10, 4, 20, 5, 30, 6, 40, 7, 50, 60, 70] 

这是条件2的预期结果。由于list2有更多元素,因此在list1耗尽后,我们将这些元素附加到list1:

 list1: [10, 20, 30, 40] list2: [4, 5, 6, 7, 8, 9, 10, 11] Combined: [10, 4, 20, 5, 30, 6, 40, 7, 8, 9, 10, 11] 

我的代码使用if-else语句来处理这两个条件。 然后我使用迭代器遍历list2的元素并将它们插入list1中。

 public static void main(String[] Args) { ArrayList numbers = new ArrayList(); numbers.add(10); numbers.add(20); numbers.add(30); numbers.add(40); //numbers.add(50); //numbers.add(60); //numbers.add(70); ArrayList numbers2 = new ArrayList(); numbers2.add(4); numbers2.add(5); numbers2.add(6); numbers2.add(7); numbers2.add(8); numbers2.add(9); numbers2.add(10); numbers2.add(11); System.out.println("list1: " + numbers); System.out.println("list2: " + numbers2); interleave(numbers, numbers2); System.out.println(); System.out.println("Combined: " + numbers); } public static void interleave(ArrayList list1, ArrayList list2) { //obtain an iterator for the collection Iterator itr2 = list2.iterator(); //loop counter int count = 1; //handle based on initial size of lists if(list1.size() >= list2.size()) { //loop through the first array and add elements from list 2 after each element while(itr2.hasNext()) { //insert elements from list2 list1.add(count, itr2.next()); //make sure elements are getting added at 1, 3, 5, 7, 9, etc count = count + 2; } } else if(list1.size() < list2.size()) { //loop through the first array and add elements from list 2 after each element while(itr2.hasNext()) { if(count <= list1.size()) { //insert elements from list2 list1.add(count, itr2.next()); //make sure elements are getting added at 1, 3, 5, 7, 9, etc count = count + 2; } else { //fill in the remainder of the elements from list2 to list1 list1.add(itr2.next()); } } } } 

你喜欢这个解决方案吗?

 public static void main(final String[] args) { ArrayList numbers = new ArrayList(); numbers.add(10); numbers.add(20); numbers.add(30); numbers.add(40); //numbers.add(50); numbers.add(60); numbers.add(70); ArrayList numbers2 = new ArrayList(); numbers2.add(4); numbers2.add(5); numbers2.add(6); numbers2.add(7); numbers2.add(8); numbers2.add(9); numbers2.add(10); numbers2.add(11); System.out.println("list1: " + numbers); System.out.println("list2: " + numbers2); List interleaved = interleave(numbers, numbers2); System.out.println("\nCombined: " + interleaved); } public static List interleave( final List list1, final List list2 ) { List result = new ArrayList(list1.size() + list2.size()); Iterator it1 = list1.iterator(); Iterator it2 = list2.iterator(); while (it1.hasNext() || it2.hasNext()) { if (it1.hasNext()) { result.add(it1.next()); } if (it2.hasNext()) { result.add(it2.next()); } } return result; } 

一些评论:

  • 我可能会返回一个新的List而不是随意修改其中一个
  • 新算法更简单:
    • 创建一个新的空列表
    • 循环计数器从0到两个列表的大小和交错的最小值
    • 完成后,检查其中一个列表是否包含更多项目并添加它们(例如,使用addAllsubList的组合)
    • 返回列表
  • 如果您不需要改变两个原始列表,可以使用以下更短的方式声明它们: List numbers = Arrays.asList(10, 20, 30, 40); – 请注意,它会创建固定大小的列表,因此您无法添加或删除
  • 使用您当前的代码,而不是重复的东西,你可以有类似的东西: List listSmall, listBig; if (list1.size() < list2.size()) { listSmall = list1; listBig = list2; } else { /* the opposite */} List listSmall, listBig; if (list1.size() < list2.size()) { listSmall = list1; listBig = list2; } else { /* the opposite */} List listSmall, listBig; if (list1.size() < list2.size()) { listSmall = list1; listBig = list2; } else { /* the opposite */} - 然后你知道listSmall是小的,你只需要一个循环。

这是另一种思考这个问题的方法,也是一种可以轻松扩展到3个列表的方法。

首先,要认识到这里要解决的难点是迭代,而不是创建新列表。 从iterable创建一个新列表是微不足道的。

所以想象我们有一个这样的方法:

 public  Iterable interleave(Iterable... lists) { return new Iterable() { @Override public Iterator iterator() { return new InterleavingIterator(lists); } }; } 

我们需要做的是一个Iterator ,它一次循环遍历每个迭代器。 这对队列来说是完美的工作(fifo)! 你的迭代器看起来像这样:

 class InterleavingIterator implements Iterator { private final Queue> iterators = new LinkedList<>(); public InterleavingIterator(Iterable> iteratables) { for ( Iterable iterable : iterables ) { Iterator iterator = iterable.iterator(); if ( iterator.hasNext() ) { this.iterators.add(iterator); } } } public boolean hasNext() { return !iterators.isEmpty(); } public T next() { Iterator nextIterator = iterators.poll(); T result = nextIterator.next(); if ( nextIterator.hasNext() ) { iterators.add(nextIterator); } return result; } } 

简而言之,每次请求下一个元素时,弹出队列顶部的迭代器,返回next()的结果,如果迭代器仍然有元素( hasNext() ),则将其放在后面队列。

对于任意数量的列表,这都完全相同,并且不需要任何icky条件检查。

要使用它创建新列表,您可以这样做:

 List combined = new ArrayList(interleave(list1, list2)); 

我提出以下代码:

 private static List joinTwoLists(List a, List b) { final boolean aIsBigger = a.size() > b.size(); final List joined = new ArrayList<>(aIsBigger ? a : b); final AtomicInteger index = new AtomicInteger(1); for (Integer value : aIsBigger ? b : a) { joined.add(index.getAndAdd(2), value); } return joined; }