All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.collect.RegularImmutableSortedMultiset Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2011 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX;
import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_HIGHER;
import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_LOWER;
import static com.google.common.collect.SortedLists.KeyPresentBehavior.ANY_PRESENT;

import com.google.common.primitives.Ints;

import java.util.Comparator;
import java.util.List;

import javax.annotation.Nullable;

/**
 * An immutable sorted multiset with one or more distinct elements.
 *
 * @author Louis Wasserman
 */
final class RegularImmutableSortedMultiset extends ImmutableSortedMultiset {
  private static final class CumulativeCountEntry extends Multisets.AbstractEntry {
    final E element;
    final int count;
    final long cumulativeCount;

    CumulativeCountEntry(E element, int count, @Nullable CumulativeCountEntry previous) {
      this.element = element;
      this.count = count;
      this.cumulativeCount = count + ((previous == null) ? 0 : previous.cumulativeCount);
    }

    @Override
    public E getElement() {
      return element;
    }

    @Override
    public int getCount() {
      return count;
    }
  }

  static  RegularImmutableSortedMultiset createFromSorted(Comparator comparator,
      List> entries) {
    List> newEntries = Lists.newArrayListWithCapacity(entries.size());
    CumulativeCountEntry previous = null;
    for (Multiset.Entry entry : entries) {
      newEntries.add(
          previous = new CumulativeCountEntry(entry.getElement(), entry.getCount(), previous));
    }
    return new RegularImmutableSortedMultiset(comparator, ImmutableList.copyOf(newEntries));
  }

  final transient ImmutableList> entries;

  RegularImmutableSortedMultiset(
      Comparator comparator, ImmutableList> entries) {
    super(comparator);
    this.entries = entries;
    assert !entries.isEmpty();
  }

  ImmutableList elementList() {
    return new TransformedImmutableList, E>(entries) {
      @Override
      E transform(CumulativeCountEntry entry) {
        return entry.getElement();
      }
    };
  }

  @Override
  ImmutableSortedSet createElementSet() {
    return new RegularImmutableSortedSet(elementList(), comparator());
  }

  @Override
  ImmutableSortedSet createDescendingElementSet() {
    return new RegularImmutableSortedSet(elementList().reverse(), reverseComparator());
  }

  @SuppressWarnings("unchecked")
  @Override
  UnmodifiableIterator> entryIterator() {
    return (UnmodifiableIterator) entries.iterator();
  }

  @SuppressWarnings("unchecked")
  @Override
  UnmodifiableIterator> descendingEntryIterator() {
    return (UnmodifiableIterator) entries.reverse().iterator();
  }

  @Override
  public CumulativeCountEntry firstEntry() {
    return entries.get(0);
  }

  @Override
  public CumulativeCountEntry lastEntry() {
    return entries.get(entries.size() - 1);
  }

  @Override
  public int size() {
    CumulativeCountEntry firstEntry = firstEntry();
    CumulativeCountEntry lastEntry = lastEntry();
    return Ints.saturatedCast(
        lastEntry.cumulativeCount - firstEntry.cumulativeCount + firstEntry.count);
  }

  @Override
  int distinctElements() {
    return entries.size();
  }

  @Override
  boolean isPartialView() {
    return entries.isPartialView();
  }

  @SuppressWarnings("unchecked")
  @Override
  public int count(@Nullable Object element) {
    if (element == null) {
      return 0;
    }
    try {
      int index = SortedLists.binarySearch(
          elementList(), (E) element, comparator(), ANY_PRESENT, INVERTED_INSERTION_INDEX);
      return (index >= 0) ? entries.get(index).getCount() : 0;
    } catch (ClassCastException e) {
      return 0;
    }
  }

  @Override
  public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) {
    int index;
    switch (boundType) {
      case OPEN:
        index = SortedLists.binarySearch(
            elementList(), checkNotNull(upperBound), comparator(), ANY_PRESENT, NEXT_HIGHER);
        break;
      case CLOSED:
        index = SortedLists.binarySearch(
            elementList(), checkNotNull(upperBound), comparator(), ANY_PRESENT, NEXT_LOWER) + 1;
        break;
      default:
        throw new AssertionError();
    }
    return createSubMultiset(0, index);
  }

  @Override
  public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) {
    int index;
    switch (boundType) {
      case OPEN:
        index = SortedLists.binarySearch(
            elementList(), checkNotNull(lowerBound), comparator(), ANY_PRESENT, NEXT_LOWER) + 1;
        break;
      case CLOSED:
        index = SortedLists.binarySearch(
            elementList(), checkNotNull(lowerBound), comparator(), ANY_PRESENT, NEXT_HIGHER);
        break;
      default:
        throw new AssertionError();
    }
    return createSubMultiset(index, distinctElements());
  }

  private ImmutableSortedMultiset createSubMultiset(int newFromIndex, int newToIndex) {
    if (newFromIndex == 0 && newToIndex == entries.size()) {
      return this;
    } else if (newFromIndex >= newToIndex) {
      return emptyMultiset(comparator());
    } else {
      return new RegularImmutableSortedMultiset(
          comparator(), entries.subList(newFromIndex, newToIndex));
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy