美文网首页
[Guava]-使用Iterators进行分组时遇见的坑

[Guava]-使用Iterators进行分组时遇见的坑

作者: 程序员驿站 | 来源:发表于2018-04-03 15:12 被阅读167次

    平常我们需要对一个大的list进行分批操作,一般使用Iterators#partition和paddedPartition方法(也可以使用Lists#partition)具体使用方式:

    List<Order> result = Lists.newArrayListWithCapacity(orders.size());
    for (List<String> orderList : Iterables.paddedPartition(orders, DEFAULT_MAX_SIZE)) {
        //doSomething.....
    }
    

    使用paddedPartition会出现一个问题,当最后一批的数据小于DEFAULT_MAX_SIZE时候,会把剩下的数据填充为null,比如

    list = [1,2,3,4,5] -------paddedPartition(list,3)-------->[[1,2],[3,4],[5,null]]

    我们看下源码

    public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
        return partitionImpl(iterator, size, true);
      }
    
      private static <T> UnmodifiableIterator<List<T>> partitionImpl(
          final Iterator<T> iterator, final int size, final boolean pad) {
        checkNotNull(iterator);
        checkArgument(size > 0);
        return new UnmodifiableIterator<List<T>>() {
          @Override
          public boolean hasNext() {
            return iterator.hasNext();
          }
    
          @Override
          public List<T> next() {
            if (!hasNext()) {
              throw new NoSuchElementException();
            }
            Object[] array = new Object[size];
            int count = 0;
            for (; count < size && iterator.hasNext(); count++) {
              array[count] = iterator.next();
            }
            for (int i = count; i < size; i++) {
              array[i] = null; // 这里重点,在这一步会判断下最后一页的剩余数据设置为null
            }
    
            @SuppressWarnings("unchecked") // we only put Ts in it
            List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
          // 这里会根据pad 判断是否返回list 还会 重新生成一个list 
            return (pad || count == size) ? list : list.subList(0, count);
          }
        };
      }
    

    我们再看下他的孪生的方法

     public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
        return partitionImpl(iterator, size, false);
      }
    
    

    都是使用的同一个方法 一个pad(填充)设置为true,一个设置的false

    另外,上面我们提到过Lists#partition的方法,他的做法是构建两个新的类实现的

    public static <T> List<List<T>> partition(List<T> list, int size) {
        checkNotNull(list);
        checkArgument(size > 0);
        return (list instanceof RandomAccess)
            ? new RandomAccessPartition<T>(list, size)
            : new Partition<T>(list, size);
      }
    

    相关文章

      网友评论

          本文标题:[Guava]-使用Iterators进行分组时遇见的坑

          本文链接:https://www.haomeiwen.com/subject/sxtchftx.html