Java-如何在特定条件下获得最佳元素列表

时间:2019-01-08 18:55:57

标签: java java-stream

class NotesDialogPagePresenterTest {

val view:NotesDialogPageContract.View= mock()
val repository:OrderSummaryRepository= mock()
val context:Context= mock()
val implNotesDialogPagePresenter :INotesDialogPagePresenter = mock()

private lateinit var presenter: NotesDialogPagePresenter
private val notes = "abcd"
private val remarks = "xyz"


@Before
fun setup() {
    whenever(view.getContext()).thenReturn(context)
    this.presenter = NotesDialogPagePresenter(view, repository)
    presenter.implNotesDialogPagePresenter = implNotesDialogPagePresenter 
}

@Test
fun onCompleteCallClicked_successTest() {

    whenever(repository.updateOrderAfterCompleteCall(notes, remarks)).thenReturn(Completable.complete())

    val spyPresenter = Mockito.spy(presenter)
    spyPresenter.onCompleteCallClicked(notes, remarks)

    verify(view, times(1)).showOnCompleteCallSuccess()
    verify(implNotesDialogPagePresenter , times(1)).updateUser()
}

我总是想从Index1开始获得最后两套

Solution{
  String question
  String answer

  public Solution(String question,String answer){
  ...
  }
}

List<Solution> solutions = new ArrayList<>();

Arrays.asList(
    new Solution("Index1","a"),
    new Solution("Index2","b"),
    new Solution("Index3","c"),
    new Solution("Index4","d"),
    new Solution("Index5","ae"),
    new Solution("Index1","afg"),
    new Solution("Index2","adfg"),
    new Solution("Index1","ag"),
    new Solution("Index2","a"),
    new Solution("Index3","a"),
    new Solution("Index4","a"),
    new Solution("Index5","a"),
    new Solution("Index1","arrr"),
    new Solution("Index2","a"),
    new Solution("Index3","a"));

但是我不确定什么是最好的方法。我可以考虑反转列表,然后在Index1上有一个以0开头的计数器 然后执行while循环将其添加到列表中,直到计数器达到2。不确定是否可以使用流。

3 个答案:

答案 0 :(得分:2)

对于普通的for循环,这比使用流要简单得多。您可以遍历列表并跟踪Index1的最后两次出现的索引。当您知道倒数第二个索引时,可以使用subList方法获取最终列表。

为使其更快,您可以从末尾向后迭代,找到前两次出现的情况。然后您可以在第二次点击Index1时停止。

此示例从头开始进行遍历:

int firstIndex = -1;
int secondIndex = -1;

for (int i = 0; i < solutions.size(); i++) {
    if (solutions.get(i).getQuestion().equals("Index1")) {
        firstIndex = secondIndex;
        secondIndex = i;
    }
}

if (firstIndex == -1) {
    // There weren't two occurrences of "Index1", so I return the whole list.
    return solutions;
}

return solutions.subList(firstIndex, solutions.size());

请注意,subList方法将返回原始列表的视图。这意味着您调用它时不会再次遍历您的列表。 这也意味着,如果您对原始列表进行了更改,则更改将反映在子列表中。

答案 1 :(得分:2)

我认为最简单的方法是获取解决方案列表中Index1出现的位置。这些代表子列表的潜在开始位置。您可以通过在解决方案列表中的索引上使用IntStream来完成此操作。然后,将倒数第二个起点作为子列表的起点,该子列表将到达列表的末尾。

    List<Integer> starts = IntStream.range(0, solutions.size())
                                    .filter(i -> solutions.get(i).getQuestion().equals("Index1"))
                                    .boxed()
                                    .collect(toList());
    if (starts.size() < 2) {
        // not sure what you want to do in this case
    } else {
        List<Solution> lastTwoSets = solutions.subList(starts.get(starts.size()-2), solutions.size());
        lastTwoSets.forEach(System.out::println);
    }

在我看来,使用int[]而不是List<Integer>会使事情变得更加高效和简洁。该技术在本质上是相同的。

    int[] starts = IntStream.range(0, solutions.size())
                            .filter(i -> solutions.get(i).question.equals("Index1"))
                            .toArray();
    if (starts.length < 2) {
        // not sure what you want to do in this case
    } else {
        List<Solution> lastTwoSets = solutions.subList(starts[starts.length-2], solutions.size());
        lastTwoSets.forEach(System.out::println);
    }

答案 2 :(得分:0)

此解决方案有点棘手,因为过滤条件是多部分的,但这可以通过计算查看问题索引的次数来完成,每个问题最多只能添加2个解决方案,然后停止一次{ {1}}被看过两次。

此条件的过滤对象为:

Index1

为确保以相反的顺序添加解决方案,将执行循环,循环从public class SolutionFilter implements Predicate<Solution> { private final Map<String, Integer> counter = new HashMap<>(); @Override public boolean test(Solution solution) { Integer index1Count = counter.get("Index1"); if (index1Count != null && index1Count == 2) { return false; } Integer count = counter.get(solution.getQuestion()); if (count == null) { counter.put(solution.getQuestion(), 1); return true; } else if (count == 1) { counter.put(solution.getQuestion(), 2); return true; } else { return false; } } } 列表的末尾开始。同样,为了确保输出列表不是相反的顺序,将使用solutions并将匹配的Deque添加到Solution的开头:

Deque

这将产生以下输出:

public static void main(final String[] args) {
    List<Solution> solutions = Arrays.asList(
        new Solution("Index1","a"),
        new Solution("Index2","b"),
        new Solution("Index3","c"),
        new Solution("Index4","d"),
        new Solution("Index5","ae"),
        new Solution("Index1","afg"),
        new Solution("Index2","adfg"),
        new Solution("Index1","ag"),
        new Solution("Index2","a"),
        new Solution("Index3","a"),
        new Solution("Index4","a"),
        new Solution("Index5","a"),
        new Solution("Index1","arrr"),
        new Solution("Index2","a"),
        new Solution("Index3","a")
    );

    SolutionFilter filter = new SolutionFilter();
    Deque<Solution> filteredSolutions = new LinkedList<>();

    for (int i = solutions.size() - 1; i > 0; i--) {

        Solution solution = solutions.get(i);

        if (filter.test(solution)) {
            filteredSolutions.addFirst(solution);
        }
    }

    System.out.println(filteredSolutions);
}

可以使用[{Index1: ag}, {Index2: a}, {Index3: a}, {Index4: a}, {Index5: a}, {Index1: arrr}, {Index2: a}, {Index3: a}] 完成此操作,但可能会更复杂。