简体   繁体   English

返回列表中的最后一项

[英]Return the last item in the list

I am returning the last item in the list.我正在返回列表中的最后一项。 One or many of the sub-lists may be null or empty.一个或多个子列表可能是 null 或为空。 If there are zero items in the list, return null.如果列表中有零项,则返回 null。 Note if the actual item is null, return null anyway.请注意,如果实际项目是 null,则无论如何返回 null。 For example, in [[10,20], [40,null]].例如,在 [[10,20], [40,null]] 中。 For basic test, you may assume, neither the list or any sublist or any item in the sub-lists is null.对于基本测试,您可以假设,列表或任何子列表或子列表中的任何项目都不是 null。

public static Integer getLastItem(ArrayList<ArrayList<Integer>> list) {
    if (list == null) {
        return null;
    }
    Integer last = null;
    for (ArrayList<Integer> data : list) {
        for (Integer o : data) {
            if (!o.equals(null)) {
                last = o;
            }
        }
    }
    return last;
}

Some reason my code is not passing the comprehensive test and gets stuck at line: assertEquals(null, ListOfListService.getLastItem(list4_nullItems)).某些原因我的代码没有通过综合测试并卡在行:assertEquals(null, ListOfListService.getLastItem(list4_nullItems))。 I have been working on it for quite some time and cannot figure it out.我已经研究了很长时间,但无法弄清楚。 The rest of the test is.测试的rest是。

@Test @Graded(description="GetLastItemComprehensive", marks=4)
public void testGetLastItemComprehensive() {
    testGetLastItemBasic();
    assertEquals(null, ListOfListService.getLastItem(null));
    assertEquals(null, ListOfListService.getLastItem(list4_nullItems));
    list4_nullItems.get(5).set(2, 24);
    assertEquals(Integer.valueOf(24), ListOfListService.getLastItem(list4_nullItems));

    ArrayList<ArrayList<Integer>> allEmptyOrNull = new ArrayList<ArrayList<Integer>>();
    allEmptyOrNull.add(null);
    allEmptyOrNull.add(new ArrayList<Integer>());
    allEmptyOrNull.add(null);
    allEmptyOrNull.add(new ArrayList<Integer>());
    assertEquals(null, ListOfListService.getLastItem(allEmptyOrNull));
    currentMethodName = new Throwable().getStackTrace()[0].getMethodName();
}

One thing that immediately caught my eye was the following line:立即引起我注意的一件事是以下行:

if (!o.equals(null)) {
    //...
}

o.equals(null) will never return true. o.equals(null)永远不会返回 true。 If o is null, a NullPointerException will be thrown instead because you're trying to invoke a method on a null object.如果o是 null,则会引发NullPointerException ,因为您正尝试调用 null object 上的方法。

To fix this, you can simply replace the expression inside the if-statement with the following line:要解决此问题,您只需将 if 语句中的表达式替换为以下行:

if (o != null) {
    //...
}

This will safely compare o to null without throwing a NullPointerException .这将安全地将o与 null 进行比较,而不会引发NullPointerException

Edit: As @AlexShesterov pointed out, this will still result in a NullPointerException if the list that is passed as an argument to getLastItem contains a null-element.编辑:正如@AlexShesterov 指出的那样,如果作为参数传递给getLastItem的列表包含空元素,这仍然会导致NullPointerException The simplest way to resolve that would be check if data is null before iterating over its elements:解决该问题的最简单方法是在遍历其元素之前检查data是否为 null:

for (ArrayList<Integer> data : list) {
    if (data != null) {
        for (Integer o : data) {
            // ...
        }
    }
}

One solution that might be considered a bit cleaner would be the following:一种可能被认为更清洁的解决方案如下:

public static Integer getLastItem(ArrayList<ArrayList<Integer>> list) {
    if (list == null) {
        return null;
    }
    // loop over each data ArrayList in reversed order
    for (int i = list.size() - 1; i >= 0; i--) {
        final ArrayList<Integer> data = list.get(i);
        // skip null elements
        if (data == null) {
            continue;
        }
        // loop over each Integer in data in reversed order
        for (int j = data.size() - 1; j >= 0; j--) {
            final Integer o = data.get(j);
            // the first Integer that was found will be the the last non-null
            // entry of the last non-null data list
            if (o != null) {
                return o;
            }
        }
    }

    // if this place is reached, no element was found, so null should be returned
    return null;
}

This way has two deciding advantages:这种方式有两个决定性的优势:

  • you don't have to loop over the the whole list each time this method is called, which improves performance for large lists每次调用此方法时,您不必遍历整个列表,这提高了大型列表的性能
  • you avoid reassignment, so the code will be easier to debug您避免重新分配,因此代码将更容易调试

Once again thanks to @AlexShesterov for motivating me to write that last abstract.再次感谢@AlexShesterov 激励我写最后一个摘要。

You may use flatMap() to flatten your ArrayList, skip all elements and get only the last one.您可以使用flatMap()来展平您的 ArrayList,跳过所有元素并仅获取最后一个元素。

Note: Optional is used to handle if last element is null and code should not throw a NullPointerException.注意: Optional 用于处理最后一个元素是否为 null 并且代码不应抛出 NullPointerException。

public static Integer fetchLastItem(ArrayList<ArrayList<Integer>> list) {
    if (list == null) {
        return null;
    }

    long size = list.stream().flatMap(l -> l.stream()).count();
    Optional<Integer> last = list.stream()
            .flatMap(l -> l.stream())
            .map(Optional::ofNullable)
            .skip(size - 1)
            .findFirst()
            .orElse(null)
             ;

    return last.orElse(null);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM