001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.util;
019
020import java.util.AbstractCollection;
021import java.util.ArrayList;
022import java.util.List;
023import java.util.NoSuchElementException;
024import org.apache.yetus.audience.InterfaceAudience;
025
026/**
027 * A collection class that contains multiple sub-lists, which allows us to not copy lists. This
028 * class does not support modification. The derived classes that add modifications are not
029 * thread-safe. NOTE: Doesn't implement list as it is not necessary for current usage, feel free to
030 * add.
031 */
032@InterfaceAudience.Private
033public class ConcatenatedLists<T> extends AbstractCollection<T> {
034  protected final ArrayList<List<T>> components = new ArrayList<>();
035  protected int size = 0;
036
037  public void addAllSublists(List<? extends List<T>> items) {
038    for (List<T> list : items) {
039      addSublist(list);
040    }
041  }
042
043  public void addSublist(List<T> items) {
044    if (!items.isEmpty()) {
045      this.components.add(items);
046      this.size += items.size();
047    }
048  }
049
050  @Override
051  public int size() {
052    return this.size;
053  }
054
055  @Override
056  public java.util.Iterator<T> iterator() {
057    return new Iterator();
058  }
059
060  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD",
061      justification = "nextWasCalled is using by StripeStoreFileManager")
062  public class Iterator implements java.util.Iterator<T> {
063    protected int currentComponent = 0;
064    protected int indexWithinComponent = -1;
065    protected boolean nextWasCalled = false;
066
067    @Override
068    public boolean hasNext() {
069      return (currentComponent + 1) < components.size()
070        || ((currentComponent + 1) == components.size()
071          && ((indexWithinComponent + 1) < components.get(currentComponent).size()));
072    }
073
074    @Override
075    public T next() {
076      if (!components.isEmpty()) {
077        this.nextWasCalled = true;
078        List<T> src = components.get(currentComponent);
079        if (++indexWithinComponent < src.size()) {
080          return src.get(indexWithinComponent);
081        }
082
083        if (++currentComponent < components.size()) {
084          indexWithinComponent = 0;
085          src = components.get(currentComponent);
086          assert src.size() > 0;
087          return src.get(indexWithinComponent);
088        }
089      }
090      this.nextWasCalled = false;
091      throw new NoSuchElementException();
092    }
093
094    @Override
095    public void remove() {
096      throw new UnsupportedOperationException();
097    }
098  }
099}