【问题标题】:Java get last element of a collectionJava获取集合的最后一个元素
【发布时间】:2012-01-11 17:53:31
【问题描述】:

我有一个集合,我想获取集合的最后一个元素。最直接、最快速的方法是什么?

一种解决方法是先toArray(),然后返回数组的最后一个元素。还有其他更好的吗?

【问题讨论】:

    标签: java collections iterator


    【解决方案1】:

    Collection 不一定是一组有序的元素,因此可能没有“最后一个”元素的概念。如果您想要订购的东西,您可以使用SortedSet,它有一个last() 方法。或者您可以使用List 并致电mylist.get(mylist.size()-1);

    如果你真的需要最后一个元素,你应该使用ListSortedSet。但是,如果你只有一个 Collection 并且你真的,真的,真的 需要最后一个元素,你可以使用 toArray() 或者你可以使用 Iterator 并迭代到末尾列表。

    例如:

    public Object getLastElement(final Collection c) {
        final Iterator itr = c.iterator();
        Object lastElement = itr.next();
        while(itr.hasNext()) {
            lastElement = itr.next();
        }
        return lastElement;
    }
    

    【讨论】:

    • 我只有可用的集合,我不知道它是数组、列表还是其他的基本类型。所以,要使用 SortedSet,我必须首先使用集合构造 SortedSet,然后再做剩下的工作。会很贵吗?
    • @tom 构建 SortedSet 可能需要 O(n*lg(n)) (如果你一次构建了它)。因此,根据您期望拥有的物品数量,它可能会相当昂贵。通常,如果您的底层类型是有序的,您至少可以将其转换为 List,即使您不知道它是什么类型的 List
    • 谢谢@Jack,假设我的数据在返回给我时已经排序,既然如此,是否还有其他解决方案?
    • @tom 如果你保证得到排序后的数据,你可以可能假设 Collection 的类型实现了SortedSet 或至少List。但是,如果您仍然无法对基础类型做出任何假设,那么您将被Collection 公开的 API 卡住,这将不容易找到最后一个元素,因为 Collection 没有概念最后一个元素。因此,您需要自己遍历并找到最后一个元素(toArray 也可以正常工作,前提是您对内存使用没有任何顾虑)。
    • 当给定一个空集合时,这会引发 NullPointerException。如果集合为空,请改用 Object lastElement = null; 返回 null。
    【解决方案2】:

    Iterables.getLast 来自 Google Guava。 它也对Lists 和SortedSets 进行了一些优化。

    【讨论】:

    • 非空安全。如果您的收藏为空,您将获得 NPE。
    • 如果您的任何内容为空,您将在 Java 中获得 NPE。检查一下。
    【解决方案3】:

    这不是非常有效的解决方案,但可以解决:

    public static <T> T getFirstElement(final Iterable<T> elements) {
        return elements.iterator().next();
    }
    
    public static <T> T getLastElement(final Iterable<T> elements) {
        T lastElement = null;
    
        for (T element : elements) {
            lastElement = element;
        }
    
        return lastElement;
    }
    

    【讨论】:

    • 其实效率很高。事实上,在不尝试将可迭代对象转换为任何更具体的类型(嗯,List)的情况下,尽可能高效。
    【解决方案4】:

    一个解决方案可能是:

    list.get(list.size()-1)
    

    编辑:您必须先将集合转换为列表,如下所示:new ArrayList(coll)

    【讨论】:

    • 所以我需要先使用集合来构造列表。性能方面,这会与 toArray 解决方案不同吗?
    • 如果您所做的只是获取最后一个元素,那么使用 toArray() 比构建 ArrayList 更有效
    • 问题提到它是一个集合而不是一个列表。现在,将它转换为列表只是为了拥有最后一个元素是一个糟糕的解决方案,如果你有大量的集合,可能会导致性能瓶颈。改用 Guava 的 Iterable.getLast 方法。
    • 如果非得让自己去转换它(它会复制它),你还不如只使用其中一种迭代解决方案...
    【解决方案5】:

    这应该可以在不转换为列表/数组的情况下工作:

    collectionName.stream().reduce((prev, next) -> next).orElse(null)
    

    【讨论】:

      【解决方案6】:

      如果您对底层集合一无所知,但知道有一个“最后一个”元素,那么一个合理的解决方案是使用迭代器。并非总是如此,并非所有集合都是有序的。

      Object lastElement = null;
      
      for (Iterator collectionItr = c.iterator(); collectionItr.hasNext(); ) {
        lastElement = collectionItr.next();
      }
      

      【讨论】:

      • 正确,我不知道集合的底层类型。但如果它是一个大集合,那么它将是一个 O(N) 解决方案。我本质上是在寻找 O(1) 的解决方案。
      • 这是不可能的。考虑尝试获取单链表的最后一个元素。该操作必须为 O(n),没有通用的 O(1) 答案。
      【解决方案7】:

      Collection 接口中没有 last()first() 方法。要获得最后一种方法,您可以在 List 上执行 get(size() - 1) 或反转 List 并执行 get(0)。我认为没有必要在任何 Collection API 中使用 last() 方法,除非您正在处理 StacksQueues

      【讨论】:

      • Collection 也没有 get 方法。
      • 当然!我的意思是 Collection 接口的 List 实现。
      【解决方案8】:

      或者您可以使用 for-each 循环:

      Collection<X> items = ...;
      X last = null;
      for (X x : items) last = x;
      

      【讨论】:

        【解决方案9】:

        如果你有 Iterable 转换为流并找到最后一个元素

         Iterator<String> sourceIterator = Arrays.asList("one", "two", "three").iterator();
        
         Iterable<String> iterable = () -> sourceIterator;
        
        
         String last = StreamSupport.stream(iterable.spliterator(), false).reduce((first, second) -> second).orElse(null);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-07
          • 2011-03-28
          • 2011-04-29
          • 2012-04-02
          • 2010-11-30
          • 1970-01-01
          • 1970-01-01
          • 2014-10-23
          相关资源
          最近更新 更多