001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import static org.apache.juneau.common.internal.ArgUtils.*; 016 017import java.util.*; 018 019/** 020 * Encapsulates multiple collections so they can be iterated over as if they were all part of the same collection. 021 * 022 * <h5 class='section'>See Also:</h5><ul> 023 024 * </ul> 025 * 026 * @param <E> The object type of this set. 027 */ 028public class MultiSet<E> extends AbstractSet<E> { 029 030 /** Inner collections. */ 031 final Collection<E>[] l; 032 033 /** 034 * Create a new Set that consists as a coalesced set of the specified collections. 035 * 036 * @param c Zero or more collections to add to this set. 037 */ 038 @SafeVarargs 039 public MultiSet(Collection<E>...c) { 040 assertArgNotNull("c", c); 041 for (Collection<E> cc : c) 042 assertArgNotNull("c", cc); 043 l = c; 044 } 045 046 /** 047 * Iterates over all entries in all collections. 048 */ 049 @Override /* Set */ 050 public Iterator<E> iterator() { 051 return new Iterator<>() { 052 int i = 0; 053 Iterator<E> i2 = (l.length > 0 ? l[i++].iterator() : null); 054 055 @Override /* Iterator */ 056 public boolean hasNext() { 057 if (i2 == null) 058 return false; 059 if (i2.hasNext()) 060 return true; 061 for (int j = i; j < l.length; j++) 062 if (l[j].size() > 0) 063 return true; 064 return false; 065 } 066 067 @Override /* Iterator */ 068 public E next() { 069 if (i2 == null) 070 throw new NoSuchElementException(); 071 while (! i2.hasNext()) { 072 if (i >= l.length) 073 throw new NoSuchElementException(); 074 i2 = l[i++].iterator(); 075 } 076 return i2.next(); 077 } 078 079 @Override /* Iterator */ 080 public void remove() { 081 if (i2 == null) 082 throw new NoSuchElementException(); 083 i2.remove(); 084 } 085 }; 086 } 087 088 /** 089 * Enumerates over all entries in all collections. 090 * 091 * @return An enumeration wrapper around this set. 092 */ 093 public Enumeration<E> enumerator() { 094 return Collections.enumeration(this); 095 } 096 097 @Override /* Set */ 098 public int size() { 099 int i = 0; 100 for (Collection<E> c : l) 101 i += c.size(); 102 return i; 103 } 104}