use latest Netty and Guava

This commit is contained in:
Sen 2025-03-16 17:40:47 +01:00
parent 7f32e87ef4
commit 3af1b1f5b6
463 changed files with 611 additions and 68249 deletions

View file

@ -42,13 +42,17 @@ import java.util.function.Function;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import game.audio.AudioInterface;
import game.audio.SoundManager;
import game.audio.Volume;
import game.biome.Biome;
import game.block.Block;
import game.collect.Lists;
import game.collect.Maps;
import game.color.Colorizer;
import game.color.TextColor;
import game.entity.Entity;
@ -56,9 +60,6 @@ import game.entity.animal.EntityHorse;
import game.entity.npc.Energy;
import game.entity.npc.EntityNPC;
import game.entity.types.EntityLiving;
import game.future.Futures;
import game.future.ListenableFuture;
import game.future.ListenableFutureTask;
import game.gui.Font;
import game.gui.Gui;
import game.gui.GuiConsole;

View file

@ -16,18 +16,19 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import game.collect.Lists;
import game.collect.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import game.color.TextColor;
import game.dimension.Dimension;
import game.dimension.Space;
import game.entity.Entity;
import game.entity.npc.EntityHuman;
import game.entity.npc.EntityNPC;
import game.future.Futures;
import game.future.ListenableFuture;
import game.future.ListenableFutureTask;
import game.future.ThreadFactoryBuilder;
import game.init.Config;
import game.init.EntityRegistry;
import game.init.UniverseRegistry;
@ -35,22 +36,6 @@ import game.log.Log;
import game.nbt.NBTLoader;
import game.nbt.NBTTagCompound;
import game.nbt.NBTTagList;
import game.net.bootstrap.ServerBootstrap;
import game.net.channel.Channel;
import game.net.channel.ChannelException;
import game.net.channel.ChannelFuture;
import game.net.channel.ChannelFutureListener;
import game.net.channel.ChannelHandler;
import game.net.channel.ChannelInitializer;
import game.net.channel.ChannelOption;
import game.net.channel.EventLoopGroup;
import game.net.channel.local.LocalAddress;
import game.net.channel.local.LocalServerChannel;
import game.net.channel.nio.NioEventLoopGroup;
import game.net.channel.socket.nio.NioServerSocketChannel;
import game.net.handler.timeout.ReadTimeoutHandler;
import game.net.util.concurrent.Future;
import game.net.util.concurrent.GenericFutureListener;
import game.network.IThreadListener;
import game.network.LazyLoadBase;
import game.network.NetConnection;
@ -84,6 +69,22 @@ import game.world.PortalType;
import game.world.Position;
import game.world.Region;
import game.world.Region.FolderInfo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.local.LocalAddress;
import io.netty.channel.local.LocalServerChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import game.world.World;
import game.world.WorldPos;
import game.world.WorldServer;

View file

@ -46,7 +46,7 @@ import game.renderer.GlState;
import game.renderer.texture.DynamicTexture;
import game.renderer.texture.EntityTexManager;
import game.renderer.texture.TextureUtil;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
public class GuiSkin extends GuiList
{
@ -666,7 +666,7 @@ import game.gui.element.Button;
import game.gui.element.TextField;
import game.network.NetHandlerPlayServer;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.world.Region;
public class GuiEdit extends GuiScreen {
@ -739,14 +739,14 @@ public class GuiEdit extends GuiScreen {
if(this.player) {
this.nameField.setMaxStringLength(16);
this.nameField.setValidator(new Predicate<String>() {
public boolean test(String name) {
public boolean apply(String name) {
return NetHandlerPlayServer.isValidUser(name);
}
});
}
else {
this.nameField.setValidator(new Predicate<String>() {
public boolean test(String name) {
public boolean apply(String name) {
for(int z = 0; z < name.length(); z++) {
if(GuiCreate.DISALLOWED_CHARS.contains(name.charAt(z)))
return false;
@ -821,7 +821,7 @@ import game.gui.element.Button;
import game.init.UniverseRegistry;
import game.network.NetHandlerPlayServer;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.world.Region;
public class GuiCreate extends GuiScreen
@ -856,7 +856,7 @@ public class GuiCreate extends GuiScreen
this.worldNameField = new TextField(this.width / 2 - 100, 60, 200, 20);
this.worldNameField.setFocused(true);
this.worldNameField.setValidator(new Predicate<String>() {
public boolean test(String name) {
public boolean apply(String name) {
for(int z = 0; z < name.length(); z++) {
if(DISALLOWED_CHARS.contains(name.charAt(z)))
return false;
@ -867,7 +867,7 @@ public class GuiCreate extends GuiScreen
this.worldUserField = new TextField(this.width / 2 - 100, 98, 200, 20);
this.worldUserField.setMaxStringLength(16);
this.worldUserField.setValidator(new Predicate<String>() {
public boolean test(String name) {
public boolean apply(String name) {
return NetHandlerPlayServer.isValidUser(name);
}
});
@ -932,7 +932,7 @@ import game.gui.element.Button;
import game.gui.server.GuiMultiplayer.ServerEntry;
import game.network.NetHandlerPlayServer;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
public class GuiServer extends GuiScreen {
private final GuiScreen parentScreen;
@ -963,7 +963,7 @@ public class GuiServer extends GuiScreen {
this.serverUserField.setMaxStringLength(16);
this.serverUserField.setText(this.serverData.user);
this.serverUserField.setValidator(new Predicate<String>() {
public boolean test(String name) {
public boolean apply(String name) {
return NetHandlerPlayServer.isValidUser(name);
}
});

View file

@ -1,13 +1,14 @@
package game.ai;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import game.entity.Entity;
import game.entity.types.EntityLiving;
import game.pathfinding.PathEntity;
import game.pathfinding.PathNavigate;
import game.util.Predicates;
import game.world.Vec3;
public class EntityAIAvoidEntity<T extends Entity> extends EntityAIBase
@ -38,7 +39,7 @@ public class EntityAIAvoidEntity<T extends Entity> extends EntityAIBase
{
this.canBeSeenSelector = new Predicate<Entity>()
{
public boolean test(Entity p_apply_1_)
public boolean apply(Entity p_apply_1_)
{
return p_apply_1_.isEntityAlive() && EntityAIAvoidEntity.this.theEntity.getEntitySenses().canSee(p_apply_1_);
}

View file

@ -1,6 +1,7 @@
package game.ai;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import game.block.BlockTallGrass;
import game.entity.animal.EntitySheep;
@ -8,7 +9,6 @@ import game.init.BlockRegistry;
import game.init.Blocks;
import game.init.Config;
import game.pattern.BlockStateHelper;
import game.util.Predicates;
import game.world.BlockPos;
import game.world.State;
import game.world.World;
@ -40,7 +40,7 @@ public class EntityAIEatGrass extends EntityAIBase
else
{
BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ);
return field_179505_b.test(this.entityWorld.getState(blockpos)) ? true : this.entityWorld.getState(blockpos.down()).getBlock() == Blocks.grass;
return field_179505_b.apply(this.entityWorld.getState(blockpos)) ? true : this.entityWorld.getState(blockpos.down()).getBlock() == Blocks.grass;
}
}
@ -89,7 +89,7 @@ public class EntityAIEatGrass extends EntityAIBase
{
BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ);
if (field_179505_b.test(this.entityWorld.getState(blockpos)))
if (field_179505_b.apply(this.entityWorld.getState(blockpos)))
{
if (Config.mobGrief)
{

View file

@ -2,7 +2,7 @@ package game.ai;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.attributes.AttributeInstance;
import game.entity.attributes.Attributes;
@ -28,7 +28,7 @@ public class EntityAIFindEntityNearest extends EntityAIBase
this.field_179443_c = new Predicate<EntityLiving>()
{
public boolean test(EntityLiving p_apply_1_)
public boolean apply(EntityLiving p_apply_1_)
{
double d0 = EntityAIFindEntityNearest.this.getFollowRange();

View file

@ -2,7 +2,8 @@ package game.ai;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.types.EntityLiving;
import game.pathfinding.PathEntity;
import game.pathfinding.PathNavigateGround;

View file

@ -3,7 +3,7 @@ package game.ai;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.Entity;
import game.entity.types.EntityLiving;
@ -37,9 +37,9 @@ public class EntityAINearestAttackableTarget<T extends EntityLiving> extends Ent
this.setMutexBits(1);
this.targetEntitySelector = new Predicate<T>()
{
public boolean test(T p_apply_1_)
public boolean apply(T p_apply_1_)
{
if (targetSelector != null && !targetSelector.test(p_apply_1_))
if (targetSelector != null && !targetSelector.apply(p_apply_1_))
{
return false;
}

View file

@ -2,8 +2,9 @@ package game.ai;
import java.util.Map;
import com.google.common.collect.Maps;
import game.block.Block;
import game.collect.Maps;
import game.entity.npc.EntityNPC;
import game.init.Blocks;
import game.init.Config;

View file

@ -1,6 +1,6 @@
package game.ai;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.types.EntityLiving;
import game.entity.types.EntityTameable;

View file

@ -3,7 +3,7 @@ package game.ai;
import java.util.Iterator;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
public class EntityAITasks
{

View file

@ -2,7 +2,8 @@ package game.ai;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.Entity;
import game.entity.types.EntityLiving;

View file

@ -7,10 +7,12 @@ import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine.Info;
import com.google.common.collect.Lists;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import game.collect.Lists;
import game.log.Log;
public class AudioInterface implements Runnable {

View file

@ -6,11 +6,12 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import game.Game;
import game.collect.BiMap;
import game.collect.HashBiMap;
import game.collect.Lists;
import game.collect.Maps;
import game.entity.npc.EntityNPC;
import game.util.ExtMath;

View file

@ -3,13 +3,14 @@ package game.biome;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import game.block.Block;
import game.block.BlockColored;
import game.block.BlockFlower;
import game.block.BlockSand;
import game.block.BlockTallGrass;
import game.collect.Lists;
import game.collect.Maps;
import game.color.Colorizer;
import game.color.DyeColor;
import game.entity.animal.EntityBat;

View file

@ -9,15 +9,16 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.Function;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.UnmodifiableIterator;
import game.audio.SoundType;
import game.collect.ImmutableList;
import game.collect.ImmutableMap;
import game.collect.Iterables;
import game.collect.Lists;
import game.collect.Maps;
import game.collect.UnmodifiableIterator;
import game.enchantment.EnchantmentHelper;
import game.entity.Entity;
import game.entity.item.EntityItem;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.Entity;
import game.entity.npc.EntityNPC;
import game.entity.projectile.EntityArrow;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.npc.EntityNPC;
import game.init.Blocks;
import game.init.Items;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.Entity;
import game.entity.npc.EntityNPC;
import game.item.CheatTab;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.Map;
import game.collect.Maps;
import com.google.common.collect.Maps;
import game.init.Blocks;
import game.init.Config;
import game.init.SoundEvent;

View file

@ -4,7 +4,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import game.collect.Sets;
import com.google.common.collect.Sets;
import game.entity.Entity;
import game.item.Item;
import game.material.Material;

View file

@ -2,10 +2,11 @@ package game.block;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import game.collect.Filter;
import game.collect.Lists;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import game.init.Blocks;
import game.init.Config;
import game.item.CheatTab;
@ -80,7 +81,7 @@ public abstract class BlockFlower extends BlockBush
{
this.type = PropertyEnum.<BlockFlower.EnumFlowerType>create("type", BlockFlower.EnumFlowerType.class, new Predicate<BlockFlower.EnumFlowerType>()
{
public boolean test(BlockFlower.EnumFlowerType p_apply_1_)
public boolean apply(BlockFlower.EnumFlowerType p_apply_1_)
{
return p_apply_1_.getBlockType() == BlockFlower.this.getBlockType();
}
@ -201,9 +202,9 @@ public abstract class BlockFlower extends BlockBush
static {
for (final BlockFlower.EnumFlowerColor blockflower$enumflowercolor : BlockFlower.EnumFlowerColor.values())
{
Collection<BlockFlower.EnumFlowerType> collection = Filter.<BlockFlower.EnumFlowerType>filter(Lists.newArrayList(values()), new Predicate<BlockFlower.EnumFlowerType>()
Collection<BlockFlower.EnumFlowerType> collection = Collections2.<BlockFlower.EnumFlowerType>filter(Lists.newArrayList(values()), new Predicate<BlockFlower.EnumFlowerType>()
{
public boolean test(BlockFlower.EnumFlowerType p_apply_1_)
public boolean apply(BlockFlower.EnumFlowerType p_apply_1_)
{
return p_apply_1_.getBlockType() == blockflower$enumflowercolor;
}

View file

@ -1,7 +1,7 @@
package game.block;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.Entity;
import game.entity.npc.EntityNPC;
@ -83,7 +83,7 @@ public class BlockHopper extends BlockContainer
public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate<Facing>()
{
public boolean test(Facing p_apply_1_)
public boolean apply(Facing p_apply_1_)
{
return p_apply_1_ != Facing.UP;
}

View file

@ -2,8 +2,9 @@ package game.block;
import java.util.List;
import com.google.common.collect.Lists;
import game.audio.SoundType;
import game.collect.Lists;
import game.color.Colorizer;
import game.entity.npc.EntityNPC;
import game.init.Blocks;

View file

@ -2,8 +2,9 @@ package game.block;
import java.util.List;
import com.google.common.collect.Lists;
import game.audio.SoundType;
import game.collect.Lists;
import game.entity.Entity;
import game.entity.types.EntityLiving;
import game.init.Blocks;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.init.Blocks;
import game.item.CheatTab;
import game.material.Material;

View file

@ -1,7 +1,8 @@
package game.block;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.Entity;
import game.entity.item.EntityCart;
@ -24,7 +25,7 @@ public class BlockRailDetector extends BlockRailBase
{
public static final PropertyEnum<BlockRailBase.EnumRailDirection> SHAPE = PropertyEnum.<BlockRailBase.EnumRailDirection>create("shape", BlockRailBase.EnumRailDirection.class, new Predicate<BlockRailBase.EnumRailDirection>()
{
public boolean test(BlockRailBase.EnumRailDirection p_apply_1_)
public boolean apply(BlockRailBase.EnumRailDirection p_apply_1_)
{
return p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_WEST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_WEST;
}
@ -156,7 +157,7 @@ public class BlockRailDetector extends BlockRailBase
// }
List<EntityCart> list1 = this.<EntityCart>findMinecarts(worldIn, pos, EntityCart.class, new Predicate<EntityCart>() {
public boolean test(EntityCart entity) {
public boolean apply(EntityCart entity) {
return entity instanceof IInventory && entity.isEntityAlive();
}
});

View file

@ -1,6 +1,6 @@
package game.block;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.properties.IProperty;
import game.properties.PropertyBool;
@ -14,7 +14,7 @@ public class BlockRailPowered extends BlockRailBase
{
public static final PropertyEnum<BlockRailBase.EnumRailDirection> SHAPE = PropertyEnum.<BlockRailBase.EnumRailDirection>create("shape", BlockRailBase.EnumRailDirection.class, new Predicate<BlockRailBase.EnumRailDirection>()
{
public boolean test(BlockRailBase.EnumRailDirection p_apply_1_)
public boolean apply(BlockRailBase.EnumRailDirection p_apply_1_)
{
return p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_WEST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_WEST;
}

View file

@ -149,7 +149,7 @@ public class BlockRedstoneComparator extends BlockRedstoneDiode implements ITile
// {
// List<EntityFrame> list = worldIn.<EntityFrame>getEntitiesWithinAABB(EntityFrame.class, new BoundingBox((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 1), (double)(pos.getZ() + 1)), new Predicate<Entity>()
// {
// public boolean test(Entity p_apply_1_)
// public boolean apply(Entity p_apply_1_)
// {
// return p_apply_1_ != null && p_apply_1_.getHorizontalFacing() == facing;
// }

View file

@ -3,8 +3,9 @@ package game.block;
import java.util.List;
import java.util.Map;
import game.collect.Lists;
import game.collect.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import game.init.Blocks;
import game.init.ItemRegistry;
import game.init.SoundEvent;

View file

@ -4,8 +4,9 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import game.collect.Lists;
import game.collect.Sets;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import game.init.Blocks;
import game.init.Items;
import game.item.Item;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.init.Blocks;
import game.init.Config;
import game.init.WoodType;

View file

@ -2,7 +2,8 @@ package game.block;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
import game.entity.Entity;
import game.entity.types.EntityLiving;
import game.item.CheatTab;

View file

@ -1,6 +1,6 @@
package game.block;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.init.Blocks;
import game.init.Config;
@ -27,7 +27,7 @@ public class BlockStem extends BlockBush implements IGrowable
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 7);
public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate<Facing>()
{
public boolean test(Facing p_apply_1_)
public boolean apply(Facing p_apply_1_)
{
return p_apply_1_ != Facing.DOWN;
}

View file

@ -1,6 +1,6 @@
package game.block;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
import game.entity.types.EntityLiving;
import game.init.Blocks;
@ -28,7 +28,7 @@ public class BlockTorch extends Block
{
public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate<Facing>()
{
public boolean test(Facing p_apply_1_)
public boolean apply(Facing p_apply_1_)
{
return p_apply_1_ != Facing.DOWN;
}

View file

@ -8,11 +8,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import game.block.Block;
import game.block.BlockDoor;
import game.block.BlockRailBase;
import game.block.ITileEntityProvider;
import game.collect.Lists;
import game.init.Blocks;
import game.init.ReorderRegistry;
import game.inventory.IInventory;

View file

@ -1,6 +1,6 @@
package game.clipboard;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
public class Rotation {
private final RotationValue[] values;
@ -9,7 +9,7 @@ public class Rotation {
public Rotation(RotationValue[] values, Predicate<Integer> predicate) {
this.values = values;
for(int z = 0; z < 16; z++) {
if(predicate != null && !predicate.test(z)) {
if(predicate != null && !predicate.apply(z)) {
this.dirFlags[z] = false;
continue;
}

View file

@ -1,399 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.CollectPreconditions.checkRemove;
import static game.collect.Preconditions.checkArgument;
import static game.collect.Preconditions.checkState;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* A general-purpose bimap implementation using any two backing {@code Map}
* instances.
*
* <p>Note that this class contains {@code equals()} calls that keep it from
* supporting {@code IdentityHashMap} backing maps.
*
* @author Kevin Bourrillion
* @author Mike Bostock
*/
abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
implements BiMap<K, V>, Serializable {
private transient Map<K, V> delegate;
transient AbstractBiMap<V, K> inverse;
/** Package-private constructor for creating a map-backed bimap. */
AbstractBiMap(Map<K, V> forward, Map<V, K> backward) {
setDelegates(forward, backward);
}
/** Private constructor for inverse bimap. */
private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) {
delegate = backward;
inverse = forward;
}
@Override protected Map<K, V> delegate() {
return delegate;
}
/**
* Returns its input, or throws an exception if this is not a valid key.
*/
K checkKey(K key) {
return key;
}
/**
* Returns its input, or throws an exception if this is not a valid value.
*/
V checkValue(V value) {
return value;
}
/**
* Specifies the delegate maps going in each direction. Called by the
* constructor and by subclasses during deserialization.
*/
void setDelegates(Map<K, V> forward, Map<V, K> backward) {
checkState(delegate == null);
checkState(inverse == null);
checkArgument(forward.isEmpty());
checkArgument(backward.isEmpty());
checkArgument(forward != backward);
delegate = forward;
inverse = new Inverse<V, K>(backward, this);
}
void setInverse(AbstractBiMap<V, K> inverse) {
this.inverse = inverse;
}
// Query Operations (optimizations)
@Override public boolean containsValue(Object value) {
return inverse.containsKey(value);
}
// Modification Operations
@Override public V put(K key, V value) {
return putInBothMaps(key, value, false);
}
@Override
public V forcePut(K key, V value) {
return putInBothMaps(key, value, true);
}
private V putInBothMaps(K key, V value, boolean force) {
checkKey(key);
checkValue(value);
boolean containedKey = containsKey(key);
if (containedKey && Preconditions.equal(value, get(key))) {
return value;
}
if (force) {
inverse().remove(value);
} else {
checkArgument(!containsValue(value), "value already present: %s", value);
}
V oldValue = delegate.put(key, value);
updateInverseMap(key, containedKey, oldValue, value);
return oldValue;
}
private void updateInverseMap(
K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
@Override public V remove(Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
private V removeFromBothMaps(Object key) {
V oldValue = delegate.remove(key);
removeFromInverseMap(oldValue);
return oldValue;
}
private void removeFromInverseMap(V oldValue) {
inverse.delegate.remove(oldValue);
}
// Bulk Operations
@Override public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override public void clear() {
delegate.clear();
inverse.delegate.clear();
}
// Views
@Override
public BiMap<V, K> inverse() {
return inverse;
}
private transient Set<K> keySet;
@Override public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
private class KeySet extends ForwardingSet<K> {
@Override protected Set<K> delegate() {
return delegate.keySet();
}
@Override public void clear() {
AbstractBiMap.this.clear();
}
@Override public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
removeFromBothMaps(key);
return true;
}
@Override public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
@Override public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
@Override public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
@Override public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the
* iteration order so that it is consistent with the forward map.
*/
Set<V> result = valueSet;
return (result == null) ? valueSet = new ValueSet() : result;
}
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
@Override protected Set<V> delegate() {
return valuesDelegate;
}
@Override public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
@Override public Object[] toArray() {
return standardToArray();
}
@Override public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
// @Override public String toString() {
// return standardToString();
// }
}
private transient Set<Entry<K, V>> entrySet;
@Override public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
@Override protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
@Override public void clear() {
AbstractBiMap.this.clear();
}
@Override public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
// safe because esDelgate.contains(object).
Entry<?, ?> entry = (Entry<?, ?>) object;
inverse.delegate.remove(entry.getValue());
/*
* Remove the mapping in inverse before removing from esDelegate because
* if entry is part of esDelegate, entry might be invalidated after the
* mapping is removed from esDelegate.
*/
esDelegate.remove(entry);
return true;
}
@Override public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
@Override protected Entry<K, V> delegate() {
return finalEntry;
}
@Override public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Preconditions.equal(value, getValue())) {
return value;
}
checkArgument(!containsValue(value),
"value already present: %s", value);
V oldValue = finalEntry.setValue(value);
checkState(Preconditions.equal(value, get(getKey())),
"entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
@Override public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
removeFromInverseMap(value);
}
};
}
// See java.util.Collections.CheckedEntrySet for details on attacks.
@Override public Object[] toArray() {
return standardToArray();
}
@Override public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
@Override public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
@Override public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** The inverse of any other {@code AbstractBiMap} subclass. */
private static class Inverse<K, V> extends AbstractBiMap<K, V> {
private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) {
super(backward, forward);
}
/*
* Serialization stores the forward bimap, the inverse of this inverse.
* Deserialization calls inverse() on the forward bimap and returns that
* inverse.
*
* If a bimap and its inverse are serialized together, the deserialized
* instances have inverse() methods that return the other.
*/
@Override
K checkKey(K key) {
return inverse.checkValue(key);
}
@Override
V checkValue(V value) {
return inverse.checkKey(value);
}
/**
* @serialData the forward bimap
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(inverse());
}
// reading data stored by writeObject
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
setInverse((AbstractBiMap<V, K>) stream.readObject());
}
Object readResolve() {
return inverse().inverse();
}
private static final long serialVersionUID = 0;
}
private static final long serialVersionUID = 0;
}

View file

@ -1,106 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import static game.collect.Preconditions.checkPositionIndex;
import java.util.NoSuchElementException;
/**
* This class provides a skeletal implementation of the {@link ListIterator}
* interface across a fixed number of elements that may be retrieved by
* position. It does not support {@link #remove}, {@link #set}, or {@link #add}.
*
* @author Jared Levy
*/
abstract class AbstractIndexedListIterator<E>
extends UnmodifiableListIterator<E> {
private final int size;
private int position;
/**
* Returns the element with the specified index. This method is called by
* {@link #next()}.
*/
protected abstract E get(int index);
/**
* Constructs an iterator across a sequence of the given size whose initial
* position is 0. That is, the first call to {@link #next()} will return the
* first element (or throw {@link NoSuchElementException} if {@code size} is
* zero).
*
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size) {
this(size, 0);
}
/**
* Constructs an iterator across a sequence of the given size with the given
* initial position. That is, the first call to {@link #nextIndex()} will
* return {@code position}, and the first call to {@link #next()} will return
* the element at that index, if available. Calls to {@link #previous()} can
* retrieve the preceding {@code position} elements.
*
* @throws IndexOutOfBoundsException if {@code position} is negative or is
* greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size, int position) {
checkPositionIndex(position, size);
this.size = size;
this.position = position;
}
@Override
public final boolean hasNext() {
return position < size;
}
@Override
public final E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return get(position++);
}
@Override
public final int nextIndex() {
return position;
}
@Override
public final boolean hasPrevious() {
return position > 0;
}
@Override
public final E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
return get(--position);
}
@Override
public final int previousIndex() {
return position - 1;
}
}

View file

@ -1,173 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.Preconditions.checkState;
import java.util.NoSuchElementException;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface, to make this interface easier to implement for certain types of
* data sources.
*
* <p>{@code Iterator} requires its implementations to support querying the
* end-of-data status without changing the iterator's state, using the {@link
* #hasNext} method. But many data sources, such as {@link
* java.io.Reader#read()}, do not expose this information; the only way to
* discover whether there is any data left is by trying to retrieve it. These
* types of data sources are ordinarily difficult to write iterators for. But
* using this class, one must implement only the {@link #computeNext} method,
* and invoke the {@link #endOfData} method when appropriate.
*
* <p>Another example is an iterator that skips over null elements in a backing
* iterator. This could be implemented as: <pre> {@code
*
* public static Iterator<String> skipNulls(final Iterator<String> in) {
* return new AbstractIterator<String>() {
* protected String computeNext() {
* while (in.hasNext()) {
* String s = in.next();
* if (s != null) {
* return s;
* }
* }
* return endOfData();
* }
* };
* }}</pre>
*
* <p>This class supports iterators that include null elements.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
// When making changes to this class, please also update the copy at
// com.google.common.base.AbstractIterator
public abstract class AbstractIterator<T> extends UnmodifiableIterator<T> {
private State state = State.NOT_READY;
/** Constructor for use by subclasses. */
protected AbstractIterator() {}
private enum State {
/** We have computed the next element and haven't returned it yet. */
READY,
/** We haven't yet computed or have already returned the element. */
NOT_READY,
/** We have reached the end of the data and are finished. */
DONE,
/** We've suffered an exception and are kaput. */
FAILED,
}
private T next;
/**
* Returns the next element. <b>Note:</b> the implementation must call {@link
* #endOfData()} when there are no elements left in the iteration. Failure to
* do so could result in an infinite loop.
*
* <p>The initial invocation of {@link #hasNext()} or {@link #next()} calls
* this method, as does the first invocation of {@code hasNext} or {@code
* next} following each successful call to {@code next}. Once the
* implementation either invokes {@code endOfData} or throws an exception,
* {@code computeNext} is guaranteed to never be called again.
*
* <p>If this method throws an exception, it will propagate outward to the
* {@code hasNext} or {@code next} invocation that invoked this method. Any
* further attempts to use the iterator will result in an {@link
* IllegalStateException}.
*
* <p>The implementation of this method may not invoke the {@code hasNext},
* {@code next}, or {@link #peek()} methods on this instance; if it does, an
* {@code IllegalStateException} will result.
*
* @return the next element if there was one. If {@code endOfData} was called
* during execution, the return value will be ignored.
* @throws RuntimeException if any unrecoverable error happens. This exception
* will propagate outward to the {@code hasNext()}, {@code next()}, or
* {@code peek()} invocation that invoked this method. Any further
* attempts to use the iterator will result in an
* {@link IllegalStateException}.
*/
protected abstract T computeNext();
/**
* Implementations of {@link #computeNext} <b>must</b> invoke this method when
* there are no elements left in the iteration.
*
* @return {@code null}; a convenience so your {@code computeNext}
* implementation can use the simple statement {@code return endOfData();}
*/
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case DONE:
return false;
case READY:
return true;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
/**
* Returns the next element in the iteration without advancing the iteration,
* according to the contract of {@link PeekingIterator#peek()}.
*
* <p>Implementations of {@code AbstractIterator} that wish to expose this
* functionality should implement {@code PeekingIterator}.
*/
public final T peek() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return next;
}
}

View file

@ -1,62 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Map.Entry;
/**
* Implementation of the {@code equals}, {@code hashCode}, and {@code toString}
* methods of {@code Entry}.
*
* @author Jared Levy
*/
abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
@Override
public abstract K getKey();
@Override
public abstract V getValue();
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override public boolean equals(Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Preconditions.equal(this.getKey(), that.getKey())
&& Preconditions.equal(this.getValue(), that.getValue());
}
return false;
}
@Override public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* Returns a string representation of the form {@code {key}={value}}.
*/
@Override public String toString() {
return getKey() + "=" + getValue();
}
}

View file

@ -1,223 +0,0 @@
/*
* Copyright (C) 2013 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 game.collect;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Skeletal, implementation-agnostic implementation of the {@link Table} interface.
*
* @author Louis Wasserman
*/
abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
@Override
public boolean containsRow(Object rowKey) {
return Maps.safeContainsKey(rowMap(), rowKey);
}
@Override
public boolean containsColumn(Object columnKey) {
return Maps.safeContainsKey(columnMap(), columnKey);
}
@Override
public Set<R> rowKeySet() {
return rowMap().keySet();
}
@Override
public Set<C> columnKeySet() {
return columnMap().keySet();
}
@Override
public boolean containsValue(Object value) {
for (Map<C, V> row : rowMap().values()) {
if (row.containsValue(value)) {
return true;
}
}
return false;
}
@Override
public boolean contains(Object rowKey, Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return row != null && Maps.safeContainsKey(row, columnKey);
}
@Override
public V get(Object rowKey, Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeGet(row, columnKey);
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public void clear() {
Iterators.clear(cellSet().iterator());
}
@Override
public V remove(Object rowKey, Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeRemove(row, columnKey);
}
@Override
public V put(R rowKey, C columnKey, V value) {
return row(rowKey).put(columnKey, value);
}
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
for (Table.Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
}
private transient Set<Cell<R, C, V>> cellSet;
@Override
public Set<Cell<R, C, V>> cellSet() {
Set<Cell<R, C, V>> result = cellSet;
return (result == null) ? cellSet = createCellSet() : result;
}
Set<Cell<R, C, V>> createCellSet() {
return new CellSet();
}
abstract Iterator<Table.Cell<R, C, V>> cellIterator();
class CellSet extends AbstractSet<Cell<R, C, V>> {
@Override
public boolean contains(Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Filter.safeContains(
row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Filter.safeRemove(
row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public Iterator<Table.Cell<R, C, V>> iterator() {
return cellIterator();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
Iterator<V> valuesIterator() {
return new TransformedIterator<Cell<R, C, V>, V>(cellSet().iterator()) {
@Override
V transform(Cell<R, C, V> cell) {
return cell.getValue();
}
};
}
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valuesIterator();
}
@Override
public boolean contains(Object o) {
return containsValue(o);
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
@Override public boolean equals(Object obj) {
return equalsImpl(this, obj);
}
static boolean equalsImpl(Table<?, ?, ?> table, Object obj) {
if (obj == table) {
return true;
} else if (obj instanceof Table) {
Table<?, ?, ?> that = (Table<?, ?, ?>) obj;
return table.cellSet().equals(that.cellSet());
} else {
return false;
}
}
@Override public int hashCode() {
return cellSet().hashCode();
}
/**
* Returns the string representation {@code rowMap().toString()}.
*/
@Override public String toString() {
return rowMap().toString();
}
}

View file

@ -1,106 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Map;
import java.util.Set;
/**
* A bimap (or "bidirectional map") is a map that preserves the uniqueness of
* its values as well as that of its keys. This constraint enables bimaps to
* support an "inverse view", which is another bimap containing the same entries
* as this bimap but with reversed keys and values.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
public interface BiMap<K, V> extends Map<K, V> {
// Modification Operations
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the given value is already bound to a
* different key in this bimap. The bimap will remain unmodified in this
* event. To avoid this exception, call {@link #forcePut} instead.
*/
@Override
V put(K key, V value);
/**
* An alternate form of {@code put} that silently removes any existing entry
* with the value {@code value} before proceeding with the {@link #put}
* operation. If the bimap previously contained the provided key-value
* mapping, this method has no effect.
*
* <p>Note that a successful call to this method could cause the size of the
* bimap to increase by one, stay the same, or even decrease by one.
*
* <p><b>Warning:</b> If an existing entry with this value is removed, the key
* for that entry is discarded and not returned.
*
* @param key the key with which the specified value is to be associated
* @param value the value to be associated with the specified key
* @return the value which was previously associated with the key, which may
* be {@code null}, or {@code null} if there was no previous entry
*/
V forcePut(K key, V value);
// Bulk Operations
/**
* {@inheritDoc}
*
* <p><b>Warning:</b> the results of calling this method may vary depending on
* the iteration order of {@code map}.
*
* @throws IllegalArgumentException if an attempt to {@code put} any
* entry fails. Note that some map entries may have been added to the
* bimap before the exception was thrown.
*/
@Override
void putAll(Map<? extends K, ? extends V> map);
// Views
/**
* {@inheritDoc}
*
* <p>Because a bimap has unique values, this method returns a {@link Set},
* instead of the {@link java.util.Collection} specified in the {@link Map}
* interface.
*/
@Override
Set<V> values();
/**
* Returns the inverse view of this bimap, which maps each of this bimap's
* values to its associated key. The two bimaps are backed by the same data;
* any changes to one will appear in the other.
*
* <p><b>Note:</b>There is no guaranteed correspondence between the iteration
* order of a bimap and that of its inverse.
*
* @return the inverse view of this bimap
*/
BiMap<V, K> inverse();
}

View file

@ -1,49 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.Preconditions.checkState;
/**
* Precondition checks useful in collection implementations.
*/
final class CollectPreconditions {
static void checkEntryNotNull(Object key, Object value) {
if (key == null) {
throw new NullPointerException("null key in entry: null=" + value);
} else if (value == null) {
throw new NullPointerException("null value in entry: " + key + "=null");
}
}
static int checkNonnegative(int value, String name) {
if (value < 0) {
throw new IllegalArgumentException(name + " cannot be negative but was: " + value);
}
return value;
}
/**
* Precondition tester for {@code Iterator.remove()} that throws an exception with a consistent
* error message.
*/
static void checkRemove(boolean canRemove) {
checkState(canRemove, "no calls to next() since the last call to remove()");
}
}

View file

@ -1,273 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import static game.collect.Preconditions.checkArgument;
import java.util.Map;
/**
* A {@code RegularImmutableTable} optimized for dense data.
*/
//@Immutable
final class DenseImmutableTable<R, C, V>
extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final ImmutableMap<R, Map<C, V>> rowMap;
private final ImmutableMap<C, Map<R, V>> columnMap;
private final int[] rowCounts;
private final int[] columnCounts;
private final V[][] values;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
private static <E> ImmutableMap<E, Integer> makeIndex(ImmutableSet<E> set) {
ImmutableMap.Builder<E, Integer> indexBuilder = ImmutableMap.builder();
int i = 0;
for (E key : set) {
indexBuilder.put(key, i);
i++;
}
return indexBuilder.build();
}
DenseImmutableTable(ImmutableList<Cell<R, C, V>> cellList,
ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
this.values = array;
this.rowKeyToIndex = makeIndex(rowSpace);
this.columnKeyToIndex = makeIndex(columnSpace);
rowCounts = new int[rowKeyToIndex.size()];
columnCounts = new int[columnKeyToIndex.size()];
int[] iterationOrderRow = new int[cellList.size()];
int[] iterationOrderColumn = new int[cellList.size()];
for (int i = 0; i < cellList.size(); i++) {
Cell<R, C, V> cell = cellList.get(i);
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
int rowIndex = rowKeyToIndex.get(rowKey);
int columnIndex = columnKeyToIndex.get(columnKey);
V existingValue = values[rowIndex][columnIndex];
checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey);
values[rowIndex][columnIndex] = cell.getValue();
rowCounts[rowIndex]++;
columnCounts[columnIndex]++;
iterationOrderRow[i] = rowIndex;
iterationOrderColumn[i] = columnIndex;
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
this.rowMap = new RowMap();
this.columnMap = new ColumnMap();
}
/**
* An immutable map implementation backed by an indexed nullable array.
*/
private abstract static class ImmutableArrayMap<K, V> extends ImmutableMap<K, V> {
private final int size;
ImmutableArrayMap(int size) {
this.size = size;
}
abstract ImmutableMap<K, Integer> keyToIndex();
// True if getValue never returns null.
private boolean isFull() {
return size == keyToIndex().size();
}
K getKey(int index) {
return keyToIndex().keySet().asList().get(index);
}
abstract V getValue(int keyIndex);
@Override
ImmutableSet<K> createKeySet() {
return isFull() ? keyToIndex().keySet() : super.createKeySet();
}
@Override
public int size() {
return size;
}
@Override
public V get(Object key) {
Integer keyIndex = keyToIndex().get(key);
return (keyIndex == null) ? null : getValue(keyIndex);
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
return new ImmutableMapEntrySet<K, V>() {
@Override ImmutableMap<K, V> map() {
return ImmutableArrayMap.this;
}
@Override
public UnmodifiableIterator<Entry<K, V>> iterator() {
return new AbstractIterator<Entry<K, V>>() {
private int index = -1;
private final int maxIndex = keyToIndex().size();
@Override
protected Entry<K, V> computeNext() {
for (index++; index < maxIndex; index++) {
V value = getValue(index);
if (value != null) {
return Maps.immutableEntry(getKey(index), value);
}
}
return endOfData();
}
};
}
};
}
}
private final class Row extends ImmutableArrayMap<C, V> {
private final int rowIndex;
Row(int rowIndex) {
super(rowCounts[rowIndex]);
this.rowIndex = rowIndex;
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[rowIndex][keyIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class Column extends ImmutableArrayMap<R, V> {
private final int columnIndex;
Column(int columnIndex) {
super(columnCounts[columnIndex]);
this.columnIndex = columnIndex;
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[keyIndex][columnIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class RowMap extends ImmutableArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowCounts.length);
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
Map<C, V> getValue(int keyIndex) {
return new Row(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
private final class ColumnMap extends ImmutableArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnCounts.length);
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
Map<R, V> getValue(int keyIndex) {
return new Column(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
@Override public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
@Override
public ImmutableMap<R, Map<C, V>> rowMap() {
return rowMap;
}
@Override public V get(Object rowKey,
Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return ((rowIndex == null) || (columnIndex == null)) ? null
: values[rowIndex][columnIndex];
}
@Override
public int size() {
return iterationOrderRow.length;
}
@Override
Cell<R, C, V> getCell(int index) {
int rowIndex = iterationOrderRow[index];
int columnIndex = iterationOrderColumn[index];
R rowKey = rowKeySet().asList().get(rowIndex);
C columnKey = columnKeySet().asList().get(columnIndex);
V value = values[rowIndex][columnIndex];
return cellOf(rowKey, columnKey, value);
}
@Override
V getValue(int index) {
return values[iterationOrderRow[index]][iterationOrderColumn[index]];
}
}

View file

@ -1,304 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
/**
* Bimap with no mappings.
*
* @author Jared Levy
*/
// // uses writeReplace(), not default serialization
final class EmptyImmutableMap extends ImmutableMap<Object, Object> {
static final EmptyImmutableMap INSTANCE = new EmptyImmutableMap();
private EmptyImmutableMap() {}
// @Override public ImmutableBiMap<Object, Object> inverse() {
// return this;
// }
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public Object get(Object key) {
return null;
}
@Override
public ImmutableSet<Entry<Object, Object>> entrySet() {
return ImmutableSet.of();
}
@Override
ImmutableSet<Entry<Object, Object>> createEntrySet() {
throw new AssertionError("should never be called");
}
// @Override
// public ImmutableSetMultimap<Object, Object> asMultimap() {
// return ImmutableSetMultimap.of();
// }
@Override
public ImmutableSet<Object> keySet() {
return ImmutableSet.of();
}
@Override
boolean isPartialView() {
return false;
}
// Object readResolve() {
// return INSTANCE; // preserve singleton property
// }
/**
* Returns the empty bimap.
*/
// Casting to any type is safe because the set will never hold any elements.
//
// public static <K, V> ImmutableBiMap<K, V> of() {
// return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
// }
/**
* Returns an immutable bimap containing a single entry.
*/
// public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
// return new SingletonImmutableBiMap<K, V>(k1, v1);
// }
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
// public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
// return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
// }
//
// /**
// * Returns an immutable map containing the given entries, in order.
// *
// * @throws IllegalArgumentException if duplicate keys or values are added
// */
// public static <K, V> ImmutableBiMap<K, V> of(
// K k1, V v1, K k2, V v2, K k3, V v3) {
// return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
// }
//
// /**
// * Returns an immutable map containing the given entries, in order.
// *
// * @throws IllegalArgumentException if duplicate keys or values are added
// */
// public static <K, V> ImmutableBiMap<K, V> of(
// K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
// return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
// entryOf(k4, v4));
// }
//
// /**
// * Returns an immutable map containing the given entries, in order.
// *
// * @throws IllegalArgumentException if duplicate keys or values are added
// */
// public static <K, V> ImmutableBiMap<K, V> of(
// K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
// return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
// entryOf(k4, v4), entryOf(k5, v5));
// }
// looking for of() with > 5 entries? Use the builder instead.
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
// public static <K, V> Builder<K, V> builder() {
// return new Builder<K, V>();
// }
/**
* A builder for creating immutable bimap instances, especially {@code public
* static final} bimaps ("constant bimaps"). Example: <pre> {@code
*
* static final ImmutableBiMap<String, Integer> WORD_TO_INT =
* new ImmutableBiMap.Builder<String, Integer>()
* .put("one", 1)
* .put("two", 2)
* .put("three", 3)
* .build();}</pre>
*
* <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods
* are even more convenient.
*
* <p>Builder instances can be reused - it is safe to call {@link #build}
* multiple times to build multiple bimaps in series. Each bimap is a superset
* of the bimaps created before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
// public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
//
// /**
// * Creates a new builder. The returned builder is equivalent to the builder
// * generated by {@link ImmutableBiMap#builder}.
// */
// public Builder() {}
//
// /**
// * Associates {@code key} with {@code value} in the built bimap. Duplicate
// * keys or values are not allowed, and will cause {@link #build} to fail.
// */
// @Override public Builder<K, V> put(K key, V value) {
// super.put(key, value);
// return this;
// }
//
// /**
// * Associates all of the given map's keys and values in the built bimap.
// * Duplicate keys or values are not allowed, and will cause {@link #build}
// * to fail.
// *
// * @throws NullPointerException if any key or value in {@code map} is null
// */
// @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
// super.putAll(map);
// return this;
// }
//
// /**
// * Returns a newly-created immutable bimap.
// *
// * @throws IllegalArgumentException if duplicate keys or values were added
// */
// @Override public ImmutableBiMap<K, V> build() {
// switch (size) {
// case 0:
// return of();
// case 1:
// return of(entries[0].getKey(), entries[0].getValue());
// default:
// return new RegularImmutableBiMap<K, V>(size, entries);
// }
// }
// }
/**
* Returns an immutable bimap containing the same entries as {@code map}. If
* {@code map} somehow contains entries with duplicate keys (for example, if
* it is a {@code SortedMap} whose comparator is not <i>consistent with
* equals</i>), the results of this method are undefined.
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*
* @throws IllegalArgumentException if two keys have the same value
* @throws NullPointerException if any key or value in {@code map} is null
*/
// public static <K, V> ImmutableBiMap<K, V> copyOf(
// Map<? extends K, ? extends V> map) {
// if (map instanceof ImmutableBiMap) {
// // safe since map is not writable
// ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
// // TODO(user): if we need to make a copy of a BiMap because the
// // forward map is a view, don't make a copy of the non-view delegate map
// if (!bimap.isPartialView()) {
// return bimap;
// }
// }
// Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
// switch (entries.length) {
// case 0:
// return of();
// case 1:
// // safe covariant cast in this context
// Entry<K, V> entry = (Entry<K, V>) entries[0];
// return of(entry.getKey(), entry.getValue());
// default:
// return new RegularImmutableBiMap<K, V>(entries);
// }
// }
// private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
// ImmutableBiMap() {}
/**
* {@inheritDoc}
*
* <p>The inverse of an {@code ImmutableBiMap} is another
* {@code ImmutableBiMap}.
*/
// @Override
// public abstract ImmutableBiMap<V, K> inverse();
/**
* Returns an immutable set of the values in this map. The values are in the
* same order as the parameters used to build this map.
*/
@Override public ImmutableSet<Object> values() {
return ImmutableSet.of();
}
/**
* Guaranteed to throw an exception and leave the bimap unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
// @Deprecated
// @Override
// public V forcePut(K key, V value) {
// throw new UnsupportedOperationException();
// }
/**
* Serialized type for all ImmutableBiMap instances. It captures the logical
* contents and they are reconstructed using public factory methods. This
* ensures that the implementation types remain as implementation details.
*
* Since the bimap is immutable, ImmutableBiMap doesn't require special logic
* for keeping the bimap and its inverse in sync during serialization, the way
* AbstractBiMap does.
*/
// private static class SerializedForm extends ImmutableMap.SerializedForm {
// SerializedForm(ImmutableBiMap<?, ?> bimap) {
// super(bimap);
// }
// @Override Object readResolve() {
// Builder<Object, Object> builder = new Builder<Object, Object>();
// return createMap(builder);
// }
// private static final long serialVersionUID = 0;
// }
//
// @Override Object writeReplace() {
// return new SerializedForm(this);
// }
}

View file

@ -1,93 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Collection;
import java.util.Set;
/**
* An empty immutable set.
*
* @author Kevin Bourrillion
*/
final class EmptyImmutableSet extends ImmutableSet<Object> {
static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
private EmptyImmutableSet() {}
@Override
public int size() {
return 0;
}
@Override public boolean isEmpty() {
return true;
}
@Override public boolean contains(Object target) {
return false;
}
@Override public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override public UnmodifiableIterator<Object> iterator() {
return Iterators.emptyIterator();
}
@Override boolean isPartialView() {
return false;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public ImmutableList<Object> asList() {
return ImmutableList.of();
}
@Override public boolean equals(Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override public final int hashCode() {
return 0;
}
@Override boolean isHashCodeFast() {
return true;
}
@Override public String toString() {
return "[]";
}
Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View file

@ -1,659 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.Preconditions.checkArgument;
import static game.collect.Preconditions.checkNotNull;
import static game.util.Predicates.and;
import static game.util.Predicates.in;
import static game.util.Predicates.not;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Predicate;
import game.util.Predicates;
/**
* Provides static methods for working with {@code Collection} instances.
*
* @author Chris Povirk
* @author Mike Bostock
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
public final class Filter {
private Filter() {}
/**
* Returns the elements of {@code unfiltered} that satisfy a predicate. The
* returned collection is a live view of {@code unfiltered}; changes to one
* affect the other.
*
* <p>The resulting collection's iterator does not support {@code remove()},
* but all other collection methods are supported. When given an element that
* doesn't satisfy the predicate, the collection's {@code add()} and {@code
* addAll()} methods throw an {@link IllegalArgumentException}. When methods
* such as {@code removeAll()} and {@code clear()} are called on the filtered
* collection, only elements that satisfy the filter will be removed from the
* underlying collection.
*
* <p>The returned collection isn't threadsafe or serializable, even if
* {@code unfiltered} is.
*
* <p>Many of the filtered collection's methods, such as {@code size()},
* iterate across every element in the underlying collection and determine
* which elements satisfy the filter. When a live view is <i>not</i> needed,
* it may be faster to copy {@code Iterables.filter(unfiltered, predicate)}
* and use the copy.
*
* <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>,
* as documented at {@link Predicate#apply}. Do not provide a predicate such
* as {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent
* with equals. (See {@link Iterables#filter(Iterable, Class)} for related
* functionality.)
*/
// TODO(kevinb): how can we omit that Iterables link when building gwt
// javadoc?
public static <E> Collection<E> filter(
Collection<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredCollection) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
}
return new FilteredCollection<E>(
checkNotNull(unfiltered), checkNotNull(predicate));
}
/**
* Delegates to {@link Collection#contains}. Returns {@code false} if the
* {@code contains} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeContains(
Collection<?> collection, Object object) {
checkNotNull(collection);
try {
return collection.contains(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* Delegates to {@link Collection#remove}. Returns {@code false} if the
* {@code remove} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeRemove(Collection<?> collection, Object object) {
checkNotNull(collection);
try {
return collection.remove(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
static class FilteredCollection<E> extends AbstractCollection<E> {
final Collection<E> unfiltered;
final Predicate<? super E> predicate;
FilteredCollection(Collection<E> unfiltered,
Predicate<? super E> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
return new FilteredCollection<E>(unfiltered,
Predicates.<E>and(predicate, newPredicate));
// .<E> above needed to compile in JDK 5
}
@Override
public boolean add(E element) {
checkArgument(predicate.test(element));
return unfiltered.add(element);
}
@Override
public boolean addAll(Collection<? extends E> collection) {
for (E element : collection) {
checkArgument(predicate.test(element));
}
return unfiltered.addAll(collection);
}
@Override
public void clear() {
Iterables.removeIf(unfiltered, predicate);
}
@Override
public boolean contains(Object element) {
if (safeContains(unfiltered, element)) {
// element is in unfiltered, so it must be an E
E e = (E) element;
return predicate.test(e);
}
return false;
}
@Override
public boolean containsAll(Collection<?> collection) {
return containsAllImpl(this, collection);
}
@Override
public boolean isEmpty() {
return !Iterables.any(unfiltered, predicate);
}
@Override
public Iterator<E> iterator() {
return Iterators.filter(unfiltered.iterator(), predicate);
}
@Override
public boolean remove(Object element) {
return contains(element) && unfiltered.remove(element);
}
@Override
public boolean removeAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, in(collection)));
}
@Override
public boolean retainAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, not(in(collection))));
}
@Override
public int size() {
return Iterators.size(iterator());
}
@Override
public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
@Override
public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
/**
* Returns a collection that applies {@code function} to each element of
* {@code fromCollection}. The returned collection is a live view of {@code
* fromCollection}; changes to one affect the other.
*
* <p>The returned collection's {@code add()} and {@code addAll()} methods
* throw an {@link UnsupportedOperationException}. All other collection
* methods are supported, as long as {@code fromCollection} supports them.
*
* <p>The returned collection isn't threadsafe or serializable, even if
* {@code fromCollection} is.
*
* <p>When a live view is <i>not</i> needed, it may be faster to copy the
* transformed collection and use the copy.
*
* <p>If the input {@code Collection} is known to be a {@code List}, consider
* {@link Lists#transform}. If only an {@code Iterable} is available, use
* {@link Iterables#transform}.
*/
// public static <F, T> Collection<T> transform(Collection<F> fromCollection,
// Function<? super F, T> function) {
// return new TransformedCollection<F, T>(fromCollection, function);
// }
//
// static class TransformedCollection<F, T> extends AbstractCollection<T> {
// final Collection<F> fromCollection;
// final Function<? super F, ? extends T> function;
//
// TransformedCollection(Collection<F> fromCollection,
// Function<? super F, ? extends T> function) {
// this.fromCollection = checkNotNull(fromCollection);
// this.function = checkNotNull(function);
// }
//
// @Override public void clear() {
// fromCollection.clear();
// }
//
// @Override public boolean isEmpty() {
// return fromCollection.isEmpty();
// }
//
// @Override public Iterator<T> iterator() {
// return Iterators.transform(fromCollection.iterator(), function);
// }
//
// @Override public int size() {
// return fromCollection.size();
// }
// }
/**
* Returns {@code true} if the collection {@code self} contains all of the
* elements in the collection {@code c}.
*
* <p>This method iterates over the specified collection {@code c}, checking
* each element returned by the iterator in turn to see if it is contained in
* the specified collection {@code self}. If all elements are so contained,
* {@code true} is returned, otherwise {@code false}.
*
* @param self a collection which might contain all elements in {@code c}
* @param c a collection whose elements might be contained by {@code self}
*/
static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
return Iterables.all(c, Predicates.in(self));
}
/**
* An implementation of {@link Collection#toString()}.
*/
// static String toStringImpl(final Collection<?> collection) {
// StringBuilder sb
// = newStringBuilderForCollection(collection.size()).append('[');
// STANDARD_JOINER.appendTo(
// sb, Iterables.transform(collection, new Function<Object, Object>() {
// @Override public Object apply(Object input) {
// return input == collection ? "(this Collection)" : input;
// }
// }));
// return sb.append(']').toString();
// }
//
// /**
// * Returns best-effort-sized StringBuilder based on the given collection size.
// */
// static StringBuilder newStringBuilderForCollection(int size) {
// checkNonnegative(size, "size");
// return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
// }
/**
* Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
*/
static <T> Collection<T> cast(Iterable<T> iterable) {
return (Collection<T>) iterable;
}
// static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null");
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable}.
*
* <p><i>Notes:</i> This is an implementation of the algorithm for
* Lexicographical Permutations Generation, described in Knuth's "The Art of
* Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The
* iteration order follows the lexicographical order. This means that
* the first permutation will be in ascending order, and the last will be in
* descending order.
*
* <p>Duplicate elements are considered equal. For example, the list [1, 1]
* will have only one permutation, instead of two. This is why the elements
* have to implement {@link Comparable}.
*
* <p>An empty iterable has only one permutation, which is an empty list.
*
* <p>This method is equivalent to
* {@code Collections2.orderedPermutations(list, Ordering.natural())}.
*
* @param elements the original iterable whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException if the specified iterable is null or has any
* null elements.
* @since 12.0
*/
// @Beta public static <E extends Comparable<? super E>>
// Collection<List<E>> orderedPermutations(Iterable<E> elements) {
// return orderedPermutations(elements, Ordering.natural());
// }
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable} using the specified {@link Comparator} for establishing
* the lexicographical ordering.
*
* <p>Examples: <pre> {@code
*
* for (List<String> perm : orderedPermutations(asList("b", "c", "a"))) {
* println(perm);
* }
* // -> ["a", "b", "c"]
* // -> ["a", "c", "b"]
* // -> ["b", "a", "c"]
* // -> ["b", "c", "a"]
* // -> ["c", "a", "b"]
* // -> ["c", "b", "a"]
*
* for (List<Integer> perm : orderedPermutations(asList(1, 2, 2, 1))) {
* println(perm);
* }
* // -> [1, 1, 2, 2]
* // -> [1, 2, 1, 2]
* // -> [1, 2, 2, 1]
* // -> [2, 1, 1, 2]
* // -> [2, 1, 2, 1]
* // -> [2, 2, 1, 1]}</pre>
*
* <p><i>Notes:</i> This is an implementation of the algorithm for
* Lexicographical Permutations Generation, described in Knuth's "The Art of
* Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The
* iteration order follows the lexicographical order. This means that
* the first permutation will be in ascending order, and the last will be in
* descending order.
*
* <p>Elements that compare equal are considered equal and no new permutations
* are created by swapping them.
*
* <p>An empty iterable has only one permutation, which is an empty list.
*
* @param elements the original iterable whose elements have to be permuted.
* @param comparator a comparator for the iterable's elements.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException If the specified iterable is null, has any
* null elements, or if the specified comparator is null.
* @since 12.0
*/
// @Beta public static <E> Collection<List<E>> orderedPermutations(
// Iterable<E> elements, Comparator<? super E> comparator) {
// return new OrderedPermutationCollection<E>(elements, comparator);
// }
// private static final class OrderedPermutationCollection<E>
// extends AbstractCollection<List<E>> {
// final ImmutableList<E> inputList;
// final Comparator<? super E> comparator;
// final int size;
//
// OrderedPermutationCollection(Iterable<E> input,
// Comparator<? super E> comparator) {
// this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
// this.comparator = comparator;
// this.size = calculateSize(inputList, comparator);
// }
//
// /**
// * The number of permutations with repeated elements is calculated as
// * follows:
// * <ul>
// * <li>For an empty list, it is 1 (base case).</li>
// * <li>When r numbers are added to a list of n-r elements, the number of
// * permutations is increased by a factor of (n choose r).</li>
// * </ul>
// */
// private static <E> int calculateSize(
// List<E> sortedInputList, Comparator<? super E> comparator) {
// long permutations = 1;
// int n = 1;
// int r = 1;
// while (n < sortedInputList.size()) {
// int comparison = comparator.compare(
// sortedInputList.get(n - 1), sortedInputList.get(n));
// if (comparison < 0) {
// // We move to the next non-repeated element.
// permutations *= binomial(n, r);
// r = 0;
// if (!isPositiveInt(permutations)) {
// return Integer.MAX_VALUE;
// }
// }
// n++;
// r++;
// }
// permutations *= binomial(n, r);
// if (!isPositiveInt(permutations)) {
// return Integer.MAX_VALUE;
// }
// return (int) permutations;
// }
//
// @Override public int size() {
// return size;
// }
//
// @Override public boolean isEmpty() {
// return false;
// }
//
// @Override public Iterator<List<E>> iterator() {
// return new OrderedPermutationIterator<E>(inputList, comparator);
// }
//
// @Override public boolean contains(Object obj) {
// if (obj instanceof List) {
// List<?> list = (List<?>) obj;
// return isPermutation(inputList, list);
// }
// return false;
// }
//
// @Override public String toString() {
// return "orderedPermutationCollection(" + inputList + ")";
// }
// }
//
// private static final class OrderedPermutationIterator<E>
// extends AbstractIterator<List<E>> {
//
// List<E> nextPermutation;
// final Comparator<? super E> comparator;
//
// OrderedPermutationIterator(List<E> list,
// Comparator<? super E> comparator) {
// this.nextPermutation = Lists.newArrayList(list);
// this.comparator = comparator;
// }
//
// @Override protected List<E> computeNext() {
// if (nextPermutation == null) {
// return endOfData();
// }
// ImmutableList<E> next = ImmutableList.copyOf(nextPermutation);
// calculateNextPermutation();
// return next;
// }
//
// void calculateNextPermutation() {
// int j = findNextJ();
// if (j == -1) {
// nextPermutation = null;
// return;
// }
//
// int l = findNextL(j);
// Collections.swap(nextPermutation, j, l);
// int n = nextPermutation.size();
// Collections.reverse(nextPermutation.subList(j + 1, n));
// }
//
// int findNextJ() {
// for (int k = nextPermutation.size() - 2; k >= 0; k--) {
// if (comparator.compare(nextPermutation.get(k),
// nextPermutation.get(k + 1)) < 0) {
// return k;
// }
// }
// return -1;
// }
//
// int findNextL(int j) {
// E ak = nextPermutation.get(j);
// for (int l = nextPermutation.size() - 1; l > j; l--) {
// if (comparator.compare(ak, nextPermutation.get(l)) < 0) {
// return l;
// }
// }
// throw new AssertionError("this statement should be unreachable");
// }
// }
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Collection}.
*
* <p><i>Notes:</i> This is an implementation of the Plain Changes algorithm
* for permutations generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2.
*
* <p>If the input list contains equal elements, some of the generated
* permutations will be equal.
*
* <p>An empty collection has only one permutation, which is an empty list.
*
* @param elements the original collection whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original collection.
* @throws NullPointerException if the specified collection is null or has any
* null elements.
* @since 12.0
*/
// @Beta public static <E> Collection<List<E>> permutations(
// Collection<E> elements) {
// return new PermutationCollection<E>(ImmutableList.copyOf(elements));
// }
//
// private static final class PermutationCollection<E>
// extends AbstractCollection<List<E>> {
// final ImmutableList<E> inputList;
//
// PermutationCollection(ImmutableList<E> input) {
// this.inputList = input;
// }
//
// @Override public int size() {
// return IntMath.factorial(inputList.size());
// }
//
// @Override public boolean isEmpty() {
// return false;
// }
//
// @Override public Iterator<List<E>> iterator() {
// return new PermutationIterator<E>(inputList);
// }
//
// @Override public boolean contains(Object obj) {
// if (obj instanceof List) {
// List<?> list = (List<?>) obj;
// return isPermutation(inputList, list);
// }
// return false;
// }
//
// @Override public String toString() {
// return "permutations(" + inputList + ")";
// }
// }
// private static class PermutationIterator<E>
// extends AbstractIterator<List<E>> {
// final List<E> list;
// final int[] c;
// final int[] o;
// int j;
//
// PermutationIterator(List<E> list) {
// this.list = new ArrayList<E>(list);
// int n = list.size();
// c = new int[n];
// o = new int[n];
// Arrays.fill(c, 0);
// Arrays.fill(o, 1);
// j = Integer.MAX_VALUE;
// }
//
// @Override protected List<E> computeNext() {
// if (j <= 0) {
// return endOfData();
// }
// ImmutableList<E> next = ImmutableList.copyOf(list);
// calculateNextPermutation();
// return next;
// }
//
// void calculateNextPermutation() {
// j = list.size() - 1;
// int s = 0;
//
// // Handle the special case of an empty list. Skip the calculation of the
// // next permutation.
// if (j == -1) {
// return;
// }
//
// while (true) {
// int q = c[j] + o[j];
// if (q < 0) {
// switchDirection();
// continue;
// }
// if (q == j + 1) {
// if (j == 0) {
// break;
// }
// s++;
// switchDirection();
// continue;
// }
//
// Collections.swap(list, j - c[j] + s, j - q + s);
// c[j] = q;
// break;
// }
// }
//
// void switchDirection() {
// o[j] = -o[j];
// j--;
// }
// }
//
// /**
// * Returns {@code true} if the second list is a permutation of the first.
// */
// private static boolean isPermutation(List<?> first,
// List<?> second) {
// if (first.size() != second.size()) {
// return false;
// }
// Multiset<?> firstMultiset = HashMultiset.create(first);
// Multiset<?> secondMultiset = HashMultiset.create(second);
// return firstMultiset.equals(secondMultiset);
// }
// private static boolean isPositiveInt(long n) {
// return n >= 0 && n <= Integer.MAX_VALUE;
// }
}

View file

@ -1,250 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Collection;
import java.util.Iterator;
/**
* A collection which forwards all its method calls to another collection.
* Subclasses should override one or more methods to modify the behavior of the
* backing collection as desired per the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* <p><b>Warning:</b> The methods of {@code ForwardingCollection} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of {@link
* #addAll}, which can lead to unexpected behavior. In this case, you should
* override {@code addAll} as well, either providing your own implementation, or
* delegating to the provided {@code standardAddAll} method.
*
* <p>The {@code standard} methods are not guaranteed to be thread-safe, even
* when all of the methods that they depend on are thread-safe.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
abstract class ForwardingCollection<E> extends ForwardingObject
implements Collection<E> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingCollection() {}
@Override protected abstract Collection<E> delegate();
@Override
public Iterator<E> iterator() {
return delegate().iterator();
}
@Override
public int size() {
return delegate().size();
}
@Override
public boolean removeAll(Collection<?> collection) {
return delegate().removeAll(collection);
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public boolean contains(Object object) {
return delegate().contains(object);
}
@Override
public boolean add(E element) {
return delegate().add(element);
}
@Override
public boolean remove(Object object) {
return delegate().remove(object);
}
@Override
public boolean containsAll(Collection<?> collection) {
return delegate().containsAll(collection);
}
@Override
public boolean addAll(Collection<? extends E> collection) {
return delegate().addAll(collection);
}
@Override
public boolean retainAll(Collection<?> collection) {
return delegate().retainAll(collection);
}
@Override
public void clear() {
delegate().clear();
}
@Override
public Object[] toArray() {
return delegate().toArray();
}
@Override
public <T> T[] toArray(T[] array) {
return delegate().toArray(array);
}
/**
* A sensible definition of {@link #contains} in terms of {@link #iterator}.
* If you override {@link #iterator}, you may wish to override {@link
* #contains} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardContains(Object object) {
return Iterators.contains(iterator(), object);
}
/**
* A sensible definition of {@link #containsAll} in terms of {@link #contains}
* . If you override {@link #contains}, you may wish to override {@link
* #containsAll} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardContainsAll(Collection<?> collection) {
return Filter.containsAllImpl(this, collection);
}
/**
* A sensible definition of {@link #addAll} in terms of {@link #add}. If you
* override {@link #add}, you may wish to override {@link #addAll} to forward
* to this implementation.
*
* @since 7.0
*/
protected boolean standardAddAll(Collection<? extends E> collection) {
return Iterators.addAll(this, collection.iterator());
}
/**
* A sensible definition of {@link #remove} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override {@link
* #iterator}, you may wish to override {@link #remove} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardRemove(Object object) {
Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
if (Preconditions.equal(iterator.next(), object)) {
iterator.remove();
return true;
}
}
return false;
}
/**
* A sensible definition of {@link #removeAll} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override {@link
* #iterator}, you may wish to override {@link #removeAll} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardRemoveAll(Collection<?> collection) {
return Iterators.removeAll(iterator(), collection);
}
/**
* A sensible definition of {@link #retainAll} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override {@link
* #iterator}, you may wish to override {@link #retainAll} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardRetainAll(Collection<?> collection) {
return Iterators.retainAll(iterator(), collection);
}
/**
* A sensible definition of {@link #clear} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override {@link
* #iterator}, you may wish to override {@link #clear} to forward to this
* implementation.
*
* @since 7.0
*/
protected void standardClear() {
Iterators.clear(iterator());
}
/**
* A sensible definition of {@link #isEmpty} as {@code !iterator().hasNext}.
* If you override {@link #isEmpty}, you may wish to override {@link #isEmpty}
* to forward to this implementation. Alternately, it may be more efficient to
* implement {@code isEmpty} as {@code size() == 0}.
*
* @since 7.0
*/
protected boolean standardIsEmpty() {
return !iterator().hasNext();
}
/**
* A sensible definition of {@link #toString} in terms of {@link #iterator}.
* If you override {@link #iterator}, you may wish to override {@link
* #toString} to forward to this implementation.
*
* @since 7.0
*/
// protected String standardToString() {
// return Collections2.toStringImpl(this);
// }
/**
* A sensible definition of {@link #toArray()} in terms of {@link
* #toArray(Object[])}. If you override {@link #toArray(Object[])}, you may
* wish to override {@link #toArray} to forward to this implementation.
*
* @since 7.0
*/
protected Object[] standardToArray() {
Object[] newArray = new Object[size()];
return toArray(newArray);
}
/**
* A sensible definition of {@link #toArray(Object[])} in terms of {@link
* #size} and {@link #iterator}. If you override either of these methods, you
* may wish to override {@link #toArray} to forward to this implementation.
*
* @since 7.0
*/
protected <T> T[] standardToArray(T[] array) {
return ObjectArrays.toArrayImpl(this, array);
}
}

View file

@ -1,302 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* A map which forwards all its method calls to another map. Subclasses should
* override one or more methods to modify the behavior of the backing map as
* desired per the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* <p><i>Warning:</i> The methods of {@code ForwardingMap} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #put} alone <i>will not</i> change the behavior of {@link
* #putAll}, which can lead to unexpected behavior. In this case, you should
* override {@code putAll} as well, either providing your own implementation, or
* delegating to the provided {@code standardPutAll} method.
*
* <p>Each of the {@code standard} methods, where appropriate, use {@link
* Objects#equal} to test equality for both keys and values. This may not be
* the desired behavior for map implementations that use non-standard notions of
* key equality, such as a {@code SortedMap} whose comparator is not consistent
* with {@code equals}.
*
* <p>The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Kevin Bourrillion
* @author Jared Levy
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
abstract class ForwardingMap<K, V> extends ForwardingObject
implements Map<K, V> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMap() {}
@Override protected abstract Map<K, V> delegate();
@Override
public int size() {
return delegate().size();
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public V remove(Object object) {
return delegate().remove(object);
}
@Override
public void clear() {
delegate().clear();
}
@Override
public boolean containsKey(Object key) {
return delegate().containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return delegate().containsValue(value);
}
@Override
public V get(Object key) {
return delegate().get(key);
}
@Override
public V put(K key, V value) {
return delegate().put(key, value);
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
delegate().putAll(map);
}
@Override
public Set<K> keySet() {
return delegate().keySet();
}
@Override
public Collection<V> values() {
return delegate().values();
}
@Override
public Set<Entry<K, V>> entrySet() {
return delegate().entrySet();
}
@Override public boolean equals(Object object) {
return object == this || delegate().equals(object);
}
@Override public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #putAll(Map)} in terms of {@link
* #put(Object, Object)}. If you override {@link #put(Object, Object)}, you
* may wish to override {@link #putAll(Map)} to forward to this
* implementation.
*
* @since 7.0
*/
// protected void standardPutAll(Map<? extends K, ? extends V> map) {
// Maps.putAllImpl(this, map);
// }
/**
* A sensible, albeit inefficient, definition of {@link #remove} in terms of
* the {@code iterator} method of {@link #entrySet}. If you override {@link
* #entrySet}, you may wish to override {@link #remove} to forward to this
* implementation.
*
* <p>Alternately, you may wish to override {@link #remove} with {@code
* keySet().remove}, assuming that approach would not lead to an infinite
* loop.
*
* @since 7.0
*/
// @Beta protected V standardRemove(Object key) {
// Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
// while (entryIterator.hasNext()) {
// Entry<K, V> entry = entryIterator.next();
// if (Objects.equal(entry.getKey(), key)) {
// V value = entry.getValue();
// entryIterator.remove();
// return value;
// }
// }
// return null;
// }
/**
* A sensible definition of {@link #clear} in terms of the {@code iterator}
* method of {@link #entrySet}. In many cases, you may wish to override
* {@link #clear} to forward to this implementation.
*
* @since 7.0
*/
// protected void standardClear() {
// Iterators.clear(entrySet().iterator());
// }
/**
* A sensible implementation of {@link Map#keySet} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
* {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove}, {@link
* ForwardingMap#size}, and the {@link Set#iterator} method of {@link
* ForwardingMap#entrySet}. In many cases, you may wish to override {@link
* ForwardingMap#keySet} to forward to this implementation or a subclass
* thereof.
*
* @since 10.0
*/
// @Beta
// protected class StandardKeySet extends Maps.KeySet<K, V> {
// /** Constructor for use by subclasses. */
// public StandardKeySet() {
// super(ForwardingMap.this);
// }
// }
/**
* A sensible, albeit inefficient, definition of {@link #containsKey} in terms
* of the {@code iterator} method of {@link #entrySet}. If you override {@link
* #entrySet}, you may wish to override {@link #containsKey} to forward to
* this implementation.
*
* @since 7.0
*/
// @Beta protected boolean standardContainsKey(Object key) {
// return Maps.containsKeyImpl(this, key);
// }
/**
* A sensible implementation of {@link Map#values} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue},
* {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the {@link
* Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases, you
* may wish to override {@link ForwardingMap#values} to forward to this
* implementation or a subclass thereof.
*
* @since 10.0
*/
// @Beta
// protected class StandardValues extends Maps.Values<K, V> {
// /** Constructor for use by subclasses. */
// public StandardValues() {
// super(ForwardingMap.this);
// }
// }
/**
* A sensible definition of {@link #containsValue} in terms of the {@code
* iterator} method of {@link #entrySet}. If you override {@link #entrySet},
* you may wish to override {@link #containsValue} to forward to this
* implementation.
*
* @since 7.0
*/
// protected boolean standardContainsValue(Object value) {
// return Maps.containsValueImpl(this, value);
// }
/**
* A sensible implementation of {@link Map#entrySet} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
* {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty}, {@link
* ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases, you
* may wish to override {@link #entrySet} to forward to this implementation
* or a subclass thereof.
*
* @since 10.0
*/
// @Beta
// protected abstract class StandardEntrySet extends Maps.EntrySet<K, V> {
// /** Constructor for use by subclasses. */
// public StandardEntrySet() {}
//
// @Override
// Map<K, V> map() {
// return ForwardingMap.this;
// }
// }
/**
* A sensible definition of {@link #isEmpty} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may
* wish to override {@link #isEmpty} to forward to this implementation.
*
* @since 7.0
*/
// protected boolean standardIsEmpty() {
// return !entrySet().iterator().hasNext();
// }
/**
* A sensible definition of {@link #equals} in terms of the {@code equals}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may
* wish to override {@link #equals} to forward to this implementation.
*
* @since 7.0
*/
// protected boolean standardEquals(Object object) {
// return Maps.equalsImpl(this, object);
// }
/**
* A sensible definition of {@link #hashCode} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may
* wish to override {@link #hashCode} to forward to this implementation.
*
* @since 7.0
*/
// protected int standardHashCode() {
// return Sets.hashCodeImpl(entrySet());
// }
/**
* A sensible definition of {@link #toString} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may
* wish to override {@link #toString} to forward to this implementation.
*
* @since 7.0
*/
// protected String standardToString() {
// return Maps.toStringImpl(this);
// }
}

View file

@ -1,122 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.Map;
import java.util.Map.Entry;
/**
* A map entry which forwards all its method calls to another map entry.
* Subclasses should override one or more methods to modify the behavior of the
* backing map entry as desired per the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* <p><i>Warning:</i> The methods of {@code ForwardingMapEntry} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #getValue} alone <i>will not</i> change the behavior of
* {@link #equals}, which can lead to unexpected behavior. In this case, you
* should override {@code equals} as well, either providing your own
* implementation, or delegating to the provided {@code standardEquals} method.
*
* <p>Each of the {@code standard} methods, where appropriate, use {@link
* Objects#equal} to test equality for both keys and values. This may not be
* the desired behavior for map implementations that use non-standard notions of
* key equality, such as the entry of a {@code SortedMap} whose comparator is
* not consistent with {@code equals}.
*
* <p>The {@code standard} methods are not guaranteed to be thread-safe, even
* when all of the methods that they depend on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
abstract class ForwardingMapEntry<K, V>
extends ForwardingObject implements Map.Entry<K, V> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMapEntry() {}
@Override protected abstract Map.Entry<K, V> delegate();
@Override
public K getKey() {
return delegate().getKey();
}
@Override
public V getValue() {
return delegate().getValue();
}
@Override
public V setValue(V value) {
return delegate().setValue(value);
}
@Override public boolean equals(Object object) {
return delegate().equals(object);
}
@Override public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #equals(Object)} in terms of {@link
* #getKey()} and {@link #getValue()}. If you override either of these
* methods, you may wish to override {@link #equals(Object)} to forward to
* this implementation.
*
* @since 7.0
*/
protected boolean standardEquals(Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Preconditions.equal(this.getKey(), that.getKey())
&& Preconditions.equal(this.getValue(), that.getValue());
}
return false;
}
/**
* A sensible definition of {@link #hashCode()} in terms of {@link #getKey()}
* and {@link #getValue()}. If you override either of these methods, you may
* wish to override {@link #hashCode()} to forward to this implementation.
*
* @since 7.0
*/
// protected int standardHashCode() {
// K k = getKey();
// V v = getValue();
// return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
// }
/**
* A sensible definition of {@link #toString} in terms of {@link
* #getKey} and {@link #getValue}. If you override either of these
* methods, you may wish to override {@link #equals} to forward to this
* implementation.
*
* @since 7.0
*/
// @Beta protected String standardToString() {
// return getKey() + "=" + getValue();
// }
}

View file

@ -1,72 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
/**
* An abstract base class for implementing the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
* The {@link #delegate()} method must be overridden to return the instance
* being decorated.
*
* <p>This class does <i>not</i> forward the {@code hashCode} and {@code equals}
* methods through to the backing object, but relies on {@code Object}'s
* implementation. This is necessary to preserve the symmetry of {@code equals}.
* Custom definitions of equality are usually based on an interface, such as
* {@code Set} or {@code List}, so that the implementation of {@code equals} can
* cast the object being tested for equality to the custom interface. {@code
* ForwardingObject} implements no such custom interfaces directly; they
* are implemented only in subclasses. Therefore, forwarding {@code equals}
* would break symmetry, as the forwarding object might consider itself equal to
* the object being tested, but the reverse could not be true. This behavior is
* consistent with the JDK's collection wrappers, such as
* {@link java.util.Collections#unmodifiableCollection}. Use an
* interface-specific subclass of {@code ForwardingObject}, such as {@link
* ForwardingList}, to preserve equality behavior, or override {@code equals}
* directly.
*
* <p>The {@code toString} method is forwarded to the delegate. Although this
* class does not implement {@link Serializable}, a serializable subclass may be
* created since this class has a parameter-less constructor.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
abstract class ForwardingObject {
/** Constructor for use by subclasses. */
protected ForwardingObject() {}
/**
* Returns the backing delegate instance that methods are forwarded to.
* Abstract subclasses generally override this method with an abstract method
* that has a more specific return type, such as {@link
* ForwardingSet#delegate}. Concrete subclasses override this method to supply
* the instance being decorated.
*/
protected abstract Object delegate();
/**
* Returns the string representation generated by the delegate's
* {@code toString} method.
*/
@Override public String toString() {
return delegate().toString();
}
/* No equals or hashCode. See class comments for details. */
}

View file

@ -1,96 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Set;
/**
* A set which forwards all its method calls to another set. Subclasses should
* override one or more methods to modify the behavior of the backing set as
* desired per the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* <p><b>Warning:</b> The methods of {@code ForwardingSet} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of {@link
* #addAll}, which can lead to unexpected behavior. In this case, you should
* override {@code addAll} as well, either providing your own implementation, or
* delegating to the provided {@code standardAddAll} method.
*
* <p>The {@code standard} methods are not guaranteed to be thread-safe, even
* when all of the methods that they depend on are thread-safe.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
abstract class ForwardingSet<E> extends ForwardingCollection<E>
implements Set<E> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingSet() {}
@Override protected abstract Set<E> delegate();
@Override public boolean equals(Object object) {
return object == this || delegate().equals(object);
}
@Override public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #removeAll} in terms of {@link #iterator}
* and {@link #remove}. If you override {@code iterator} or {@code remove},
* you may wish to override {@link #removeAll} to forward to this
* implementation.
*
* @since 7.0 (this version overrides the {@code ForwardingCollection} version as of 12.0)
*/
@Override
protected boolean standardRemoveAll(Collection<?> collection) {
return Sets.removeAllImpl(this, checkNotNull(collection)); // for GWT
}
/**
* A sensible definition of {@link #equals} in terms of {@link #size} and
* {@link #containsAll}. If you override either of those methods, you may wish
* to override {@link #equals} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardEquals(Object object) {
return Sets.equalsImpl(this, object);
}
/**
* A sensible definition of {@link #hashCode} in terms of {@link #iterator}.
* If you override {@link #iterator}, you may wish to override {@link #equals}
* to forward to this implementation.
*
* @since 7.0
*/
protected int standardHashCode() {
return Sets.hashCodeImpl(this);
}
}

View file

@ -1,658 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.CollectPreconditions.checkNonnegative;
import static game.collect.CollectPreconditions.checkRemove;
import static game.collect.Preconditions.checkArgument;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* A {@link BiMap} backed by two hash tables. This implementation allows null keys and values. A
* {@code HashBiMap} and its inverse are both serializable.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap"> {@code BiMap}
* </a>.
*
* @author Louis Wasserman
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable {
/**
* Returns a new, empty {@code HashBiMap} with the default initial capacity (16).
*/
public static <K, V> HashBiMap<K, V> create() {
return create(16);
}
/**
* Constructs a new, empty bimap with the specified expected size.
*
* @param expectedSize the expected number of entries
* @throws IllegalArgumentException if the specified expected size is negative
*/
public static <K, V> HashBiMap<K, V> create(int expectedSize) {
return new HashBiMap<K, V>(expectedSize);
}
/**
* Constructs a new bimap containing initial values from {@code map}. The bimap is created with an
* initial capacity sufficient to hold the mappings in the specified map.
*/
public static <K, V> HashBiMap<K, V> create(Map<? extends K, ? extends V> map) {
HashBiMap<K, V> bimap = create(map.size());
bimap.putAll(map);
return bimap;
}
private static final class BiEntry<K, V> extends ImmutableEntry<K, V> {
final int keyHash;
final int valueHash;
BiEntry<K, V> nextInKToVBucket;
BiEntry<K, V> nextInVToKBucket;
BiEntry(K key, int keyHash, V value, int valueHash) {
super(key, value);
this.keyHash = keyHash;
this.valueHash = valueHash;
}
}
private static final double LOAD_FACTOR = 1.0;
private transient BiEntry<K, V>[] hashTableKToV;
private transient BiEntry<K, V>[] hashTableVToK;
private transient int size;
private transient int mask;
private transient int modCount;
private HashBiMap(int expectedSize) {
init(expectedSize);
}
private void init(int expectedSize) {
checkNonnegative(expectedSize, "expectedSize");
int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR);
this.hashTableKToV = createTable(tableSize);
this.hashTableVToK = createTable(tableSize);
this.mask = tableSize - 1;
this.modCount = 0;
this.size = 0;
}
/**
* Finds and removes {@code entry} from the bucket linked lists in both the
* key-to-value direction and the value-to-key direction.
*/
private void delete(BiEntry<K, V> entry) {
int keyBucket = entry.keyHash & mask;
BiEntry<K, V> prevBucketEntry = null;
for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true;
bucketEntry = bucketEntry.nextInKToVBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
hashTableKToV[keyBucket] = entry.nextInKToVBucket;
} else {
prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket;
}
break;
}
prevBucketEntry = bucketEntry;
}
int valueBucket = entry.valueHash & mask;
prevBucketEntry = null;
for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];;
bucketEntry = bucketEntry.nextInVToKBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
hashTableVToK[valueBucket] = entry.nextInVToKBucket;
} else {
prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket;
}
break;
}
prevBucketEntry = bucketEntry;
}
size--;
modCount++;
}
private void insert(BiEntry<K, V> entry) {
int keyBucket = entry.keyHash & mask;
entry.nextInKToVBucket = hashTableKToV[keyBucket];
hashTableKToV[keyBucket] = entry;
int valueBucket = entry.valueHash & mask;
entry.nextInVToKBucket = hashTableVToK[valueBucket];
hashTableVToK[valueBucket] = entry;
size++;
modCount++;
}
private static int hash(Object o) {
return Hashing.smear((o == null) ? 0 : o.hashCode());
}
private BiEntry<K, V> seekByKey(Object key, int keyHash) {
for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null;
entry = entry.nextInKToVBucket) {
if (keyHash == entry.keyHash && Preconditions.equal(key, entry.key)) {
return entry;
}
}
return null;
}
private BiEntry<K, V> seekByValue(Object value, int valueHash) {
for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null;
entry = entry.nextInVToKBucket) {
if (valueHash == entry.valueHash && Preconditions.equal(value, entry.value)) {
return entry;
}
}
return null;
}
@Override
public boolean containsKey(Object key) {
return seekByKey(key, hash(key)) != null;
}
@Override
public boolean containsValue(Object value) {
return seekByValue(value, hash(value)) != null;
}
@Override
public V get(Object key) {
BiEntry<K, V> entry = seekByKey(key, hash(key));
return (entry == null) ? null : entry.value;
}
@Override
public V put(K key, V value) {
return put(key, value, false);
}
@Override
public V forcePut(K key, V value) {
return put(key, value, true);
}
private V put(K key, V value, boolean force) {
int keyHash = hash(key);
int valueHash = hash(value);
BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash
&& Preconditions.equal(value, oldEntryForKey.value)) {
return value;
}
BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
if (oldEntryForValue != null) {
if (force) {
delete(oldEntryForValue);
} else {
throw new IllegalArgumentException("value already present: " + value);
}
}
if (oldEntryForKey != null) {
delete(oldEntryForKey);
}
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
insert(newEntry);
rehashIfNecessary();
return (oldEntryForKey == null) ? null : oldEntryForKey.value;
}
private K putInverse(V value, K key, boolean force) {
int valueHash = hash(value);
int keyHash = hash(key);
BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash
&& Preconditions.equal(key, oldEntryForValue.key)) {
return key;
}
BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
if (oldEntryForKey != null) {
if (force) {
delete(oldEntryForKey);
} else {
throw new IllegalArgumentException("value already present: " + key);
}
}
if (oldEntryForValue != null) {
delete(oldEntryForValue);
}
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
insert(newEntry);
rehashIfNecessary();
return (oldEntryForValue == null) ? null : oldEntryForValue.key;
}
private void rehashIfNecessary() {
BiEntry<K, V>[] oldKToV = hashTableKToV;
if (Hashing.needsResizing(size, oldKToV.length, LOAD_FACTOR)) {
int newTableSize = oldKToV.length * 2;
this.hashTableKToV = createTable(newTableSize);
this.hashTableVToK = createTable(newTableSize);
this.mask = newTableSize - 1;
this.size = 0;
for (int bucket = 0; bucket < oldKToV.length; bucket++) {
BiEntry<K, V> entry = oldKToV[bucket];
while (entry != null) {
BiEntry<K, V> nextEntry = entry.nextInKToVBucket;
insert(entry);
entry = nextEntry;
}
}
this.modCount++;
}
}
private BiEntry<K, V>[] createTable(int length) {
return new BiEntry[length];
}
@Override
public V remove(Object key) {
BiEntry<K, V> entry = seekByKey(key, hash(key));
if (entry == null) {
return null;
} else {
delete(entry);
return entry.value;
}
}
@Override
public void clear() {
size = 0;
Arrays.fill(hashTableKToV, null);
Arrays.fill(hashTableVToK, null);
modCount++;
}
@Override
public int size() {
return size;
}
abstract class Itr<T> implements Iterator<T> {
int nextBucket = 0;
BiEntry<K, V> next = null;
BiEntry<K, V> toRemove = null;
int expectedModCount = modCount;
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
@Override
public boolean hasNext() {
checkForConcurrentModification();
if (next != null) {
return true;
}
while (nextBucket < hashTableKToV.length) {
if (hashTableKToV[nextBucket] != null) {
next = hashTableKToV[nextBucket++];
return true;
}
nextBucket++;
}
return false;
}
@Override
public T next() {
checkForConcurrentModification();
if (!hasNext()) {
throw new NoSuchElementException();
}
BiEntry<K, V> entry = next;
next = entry.nextInKToVBucket;
toRemove = entry;
return output(entry);
}
@Override
public void remove() {
checkForConcurrentModification();
checkRemove(toRemove != null);
delete(toRemove);
expectedModCount = modCount;
toRemove = null;
}
abstract T output(BiEntry<K, V> entry);
}
@Override
public Set<K> keySet() {
return new KeySet();
}
private final class KeySet extends Maps.KeySet<K, V> {
KeySet() {
super(HashBiMap.this);
}
@Override
public Iterator<K> iterator() {
return new Itr<K>() {
@Override
K output(BiEntry<K, V> entry) {
return entry.key;
}
};
}
@Override
public boolean remove(Object o) {
BiEntry<K, V> entry = seekByKey(o, hash(o));
if (entry == null) {
return false;
} else {
delete(entry);
return true;
}
}
}
@Override
public Set<V> values() {
return inverse().keySet();
}
@Override
public Set<Entry<K, V>> entrySet() {
return new EntrySet();
}
private final class EntrySet extends Maps.EntrySet<K, V> {
@Override
Map<K, V> map() {
return HashBiMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new Itr<Entry<K, V>>() {
@Override
Entry<K, V> output(BiEntry<K, V> entry) {
return new MapEntry(entry);
}
class MapEntry extends AbstractMapEntry<K, V> {
BiEntry<K, V> delegate;
MapEntry(BiEntry<K, V> entry) {
this.delegate = entry;
}
@Override public K getKey() {
return delegate.key;
}
@Override public V getValue() {
return delegate.value;
}
@Override public V setValue(V value) {
V oldValue = delegate.value;
int valueHash = hash(value);
if (valueHash == delegate.valueHash && Preconditions.equal(value, oldValue)) {
return value;
}
checkArgument(
seekByValue(value, valueHash) == null, "value already present: %s", value);
delete(delegate);
BiEntry<K, V> newEntry =
new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
insert(newEntry);
expectedModCount = modCount;
if (toRemove == delegate) {
toRemove = newEntry;
}
delegate = newEntry;
return oldValue;
}
}
};
}
}
private transient BiMap<V, K> inverse;
@Override
public BiMap<V, K> inverse() {
return (inverse == null) ? inverse = new Inverse() : inverse;
}
private final class Inverse extends AbstractMap<V, K> implements BiMap<V, K>, Serializable {
BiMap<K, V> forward() {
return HashBiMap.this;
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
forward().clear();
}
@Override
public boolean containsKey(Object value) {
return forward().containsValue(value);
}
@Override
public K get(Object value) {
BiEntry<K, V> entry = seekByValue(value, hash(value));
return (entry == null) ? null : entry.key;
}
@Override
public K put(V value, K key) {
return putInverse(value, key, false);
}
@Override
public K forcePut(V value, K key) {
return putInverse(value, key, true);
}
@Override
public K remove(Object value) {
BiEntry<K, V> entry = seekByValue(value, hash(value));
if (entry == null) {
return null;
} else {
delete(entry);
return entry.key;
}
}
@Override
public BiMap<K, V> inverse() {
return forward();
}
@Override
public Set<V> keySet() {
return new InverseKeySet();
}
private final class InverseKeySet extends Maps.KeySet<V, K> {
InverseKeySet() {
super(Inverse.this);
}
@Override
public boolean remove(Object o) {
BiEntry<K, V> entry = seekByValue(o, hash(o));
if (entry == null) {
return false;
} else {
delete(entry);
return true;
}
}
@Override
public Iterator<V> iterator() {
return new Itr<V>() {
@Override V output(BiEntry<K, V> entry) {
return entry.value;
}
};
}
}
@Override
public Set<K> values() {
return forward().keySet();
}
@Override
public Set<Entry<V, K>> entrySet() {
return new Maps.EntrySet<V, K>() {
@Override
Map<V, K> map() {
return Inverse.this;
}
@Override
public Iterator<Entry<V, K>> iterator() {
return new Itr<Entry<V, K>>() {
@Override
Entry<V, K> output(BiEntry<K, V> entry) {
return new InverseEntry(entry);
}
class InverseEntry extends AbstractMapEntry<V, K> {
BiEntry<K, V> delegate;
InverseEntry(BiEntry<K, V> entry) {
this.delegate = entry;
}
@Override
public V getKey() {
return delegate.value;
}
@Override
public K getValue() {
return delegate.key;
}
@Override
public K setValue(K key) {
K oldKey = delegate.key;
int keyHash = hash(key);
if (keyHash == delegate.keyHash && Preconditions.equal(key, oldKey)) {
return key;
}
checkArgument(seekByKey(key, keyHash) == null, "value already present: %s", key);
delete(delegate);
BiEntry<K, V> newEntry =
new BiEntry<K, V>(key, keyHash, delegate.value, delegate.valueHash);
insert(newEntry);
expectedModCount = modCount;
// This is safe because entries can only get bumped up to earlier in the iteration,
// so they can't get revisited.
return oldKey;
}
}
};
}
};
}
Object writeReplace() {
return new InverseSerializedForm<K, V>(HashBiMap.this);
}
}
private static final class InverseSerializedForm<K, V> implements Serializable {
private final HashBiMap<K, V> bimap;
InverseSerializedForm(HashBiMap<K, V> bimap) {
this.bimap = bimap;
}
Object readResolve() {
return bimap.inverse();
}
}
/**
* @serialData the number of entries, first key, first value, second key, second value, and so on.
*/
//
// private void writeObject(ObjectOutputStream stream) throws IOException {
// stream.defaultWriteObject();
// Serialization.writeMap(this, stream);
// }
//
//
// private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
// stream.defaultReadObject();
// int size = Serialization.readCount(stream);
// init(size);
// Serialization.populateMap(this, stream, size);
// }
private static final long serialVersionUID = 0;
}

View file

@ -1,67 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
/**
* Static methods for implementing hash-based collections.
*
* @author Kevin Bourrillion
* @author Jesse Wilson
* @author Austin Appleby
*/
final class Hashing {
private Hashing() {}
private static final int C1 = 0xcc9e2d51;
private static final int C2 = 0x1b873593;
/*
* This method was rewritten in Java from an intermediate step of the Murmur hash function in
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which contained the
* following header:
*
* MurmurHash3 was written by Austin Appleby, and is placed in the public domain. The author
* hereby disclaims copyright to this source code.
*/
static int smear(int hashCode) {
return C2 * Integer.rotateLeft(hashCode * C1, 15);
}
static int smearedHash(Object o) {
return smear((o == null) ? 0 : o.hashCode());
}
private static int MAX_TABLE_SIZE = 1 << (Integer.SIZE - 2);
static int closedTableSize(int expectedEntries, double loadFactor) {
// Get the recommended table size.
// Round down to the nearest power of 2.
expectedEntries = Math.max(expectedEntries, 2);
int tableSize = Integer.highestOneBit(expectedEntries);
// Check to make sure that we will not exceed the maximum load factor.
if (expectedEntries > (int) (loadFactor * tableSize)) {
tableSize <<= 1;
return (tableSize > 0) ? tableSize : MAX_TABLE_SIZE;
}
return tableSize;
}
static boolean needsResizing(int size, int tableSize, double loadFactor) {
return size > loadFactor * tableSize && tableSize < MAX_TABLE_SIZE;
}
}

View file

@ -1,81 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
* List returned by {@link ImmutableCollection#asList} that delegates {@code contains} checks
* to the backing collection.
*
* @author Jared Levy
* @author Louis Wasserman
*/
abstract class ImmutableAsList<E> extends ImmutableList<E> {
abstract ImmutableCollection<E> delegateCollection();
@Override public boolean contains(Object target) {
// The collection's contains() is at least as fast as ImmutableList's
// and is often faster.
return delegateCollection().contains(target);
}
@Override
public int size() {
return delegateCollection().size();
}
@Override
public boolean isEmpty() {
return delegateCollection().isEmpty();
}
@Override
boolean isPartialView() {
return delegateCollection().isPartialView();
}
/**
* Serialized form that leads to the same performance as the original list.
*/
static class SerializedForm implements Serializable {
final ImmutableCollection<?> collection;
SerializedForm(ImmutableCollection<?> collection) {
this.collection = collection;
}
Object readResolve() {
return collection.asList();
}
private static final long serialVersionUID = 0;
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
@Override Object writeReplace() {
return new SerializedForm(delegateCollection());
}
}

View file

@ -1,360 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.CollectPreconditions.checkNonnegative;
import static game.collect.ObjectArrays.checkElementsNotNull;
import static game.collect.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
/**
* An immutable collection. Does not permit null elements.
*
* <p>In addition to the {@link Collection} methods, this class has an {@link
* #asList()} method, which returns a list view of the collection's elements.
*
* <p><b>Note:</b> Although this class is not final, it cannot be subclassed
* outside of this package as it has no public or protected constructors. Thus,
* instances of this type are guaranteed to be immutable.
*
* @author Jesse Wilson
* @since 2.0 (imported from Google Collections Library)
*/
// we're overriding default serialization
abstract class ImmutableCollection<E> extends AbstractCollection<E>
implements Serializable {
ImmutableCollection() {}
/**
* Returns an unmodifiable iterator across the elements in this collection.
*/
@Override
public abstract UnmodifiableIterator<E> iterator();
@Override
public final Object[] toArray() {
int size = size();
if (size == 0) {
return ObjectArrays.EMPTY_ARRAY;
}
Object[] result = new Object[size()];
copyIntoArray(result, 0);
return result;
}
@Override
public final <T> T[] toArray(T[] other) {
checkNotNull(other);
int size = size();
if (other.length < size) {
other = ObjectArrays.newArray(other, size);
} else if (other.length > size) {
other[size] = null;
}
copyIntoArray(other, 0);
return other;
}
@Override
public boolean contains(Object object) {
return object != null && super.contains(object);
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean add(E e) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean remove(Object object) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean addAll(Collection<? extends E> newElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean removeAll(Collection<?> oldElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean retainAll(Collection<?> elementsToKeep) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void clear() {
throw new UnsupportedOperationException();
}
/*
* TODO(kevinb): Restructure code so ImmutableList doesn't contain this
* variable, which it doesn't use.
*/
private transient ImmutableList<E> asList;
/**
* Returns a list view of the collection.
*
* @since 2.0
*/
public ImmutableList<E> asList() {
ImmutableList<E> list = asList;
return (list == null) ? (asList = createAsList()) : list;
}
ImmutableList<E> createAsList() {
switch (size()) {
case 0:
return ImmutableList.of();
// case 1:
// return ImmutableList.of(iterator().next());
default:
return new RegularImmutableAsList<E>(this, toArray());
}
}
/**
* Returns {@code true} if this immutable collection's implementation contains references to
* user-created objects that aren't accessible via this collection's methods. This is generally
* used to determine whether {@code copyOf} implementations should make an explicit copy to avoid
* memory leaks.
*/
abstract boolean isPartialView();
/**
* Copies the contents of this immutable collection into the specified array at the specified
* offset. Returns {@code offset + size()}.
*/
int copyIntoArray(Object[] dst, int offset) {
for (E e : this) {
dst[offset++] = e;
}
return offset;
}
Object writeReplace() {
// We serialize by default to ImmutableList, the simplest thing that works.
return new ImmutableList.SerializedForm(toArray());
}
/**
* Abstract base class for builders of {@link ImmutableCollection} types.
*
* @since 10.0
*/
public abstract static class Builder<E> {
static final int DEFAULT_INITIAL_CAPACITY = 4;
static int expandedCapacity(int oldCapacity, int minCapacity) {
if (minCapacity < 0) {
throw new AssertionError("cannot store more than MAX_VALUE elements");
}
// careful of overflow!
int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
if (newCapacity < minCapacity) {
newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;
}
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
// guaranteed to be >= newCapacity
}
return newCapacity;
}
Builder() {
}
/**
* Adds {@code element} to the {@code ImmutableCollection} being built.
*
* <p>Note that each builder class covariantly returns its own type from
* this method.
*
* @param element the element to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code element} is null
*/
public abstract Builder<E> add(E element);
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>Note that each builder class overrides this method in order to
* covariantly return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
public Builder<E> add(E... elements) {
for (E element : elements) {
add(element);
}
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>Note that each builder class overrides this method in order to
* covariantly return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
public Builder<E> addAll(Iterable<? extends E> elements) {
for (E element : elements) {
add(element);
}
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>Note that each builder class overrides this method in order to
* covariantly return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
public Builder<E> addAll(Iterator<? extends E> elements) {
while (elements.hasNext()) {
add(elements.next());
}
return this;
}
/**
* Returns a newly-created {@code ImmutableCollection} of the appropriate
* type, containing the elements provided to this builder.
*
* <p>Note that each builder class covariantly returns the appropriate type
* of {@code ImmutableCollection} from this method.
*/
public abstract ImmutableCollection<E> build();
}
abstract static class ArrayBasedBuilder<E> extends ImmutableCollection.Builder<E> {
Object[] contents;
int size;
ArrayBasedBuilder(int initialCapacity) {
checkNonnegative(initialCapacity, "initialCapacity");
this.contents = new Object[initialCapacity];
this.size = 0;
}
/**
* Expand the absolute capacity of the builder so it can accept at least
* the specified number of elements without being resized.
*/
private void ensureCapacity(int minCapacity) {
if (contents.length < minCapacity) {
this.contents = ObjectArrays.arraysCopyOf(
this.contents, expandedCapacity(contents.length, minCapacity));
}
}
@Override
public ArrayBasedBuilder<E> add(E element) {
checkNotNull(element);
ensureCapacity(size + 1);
contents[size++] = element;
return this;
}
@Override
public Builder<E> add(E... elements) {
checkElementsNotNull(elements);
ensureCapacity(size + elements.length);
System.arraycopy(elements, 0, contents, size, elements.length);
size += elements.length;
return this;
}
@Override
public Builder<E> addAll(Iterable<? extends E> elements) {
if (elements instanceof Collection) {
Collection<?> collection = (Collection<?>) elements;
ensureCapacity(size + collection.size());
}
super.addAll(elements);
return this;
}
}
}

View file

@ -1,48 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.io.Serializable;
/**
* @see com.google.common.collect.Maps#immutableEntry(Object, Object)
*/
class ImmutableEntry<K, V> extends AbstractMapEntry<K, V>
implements Serializable {
final K key;
final V value;
ImmutableEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override public final K getKey() {
return key;
}
@Override public final V getValue() {
return value;
}
@Override public final V setValue(V value) {
throw new UnsupportedOperationException();
}
private static final long serialVersionUID = 0;
}

View file

@ -1,146 +0,0 @@
/*
* Copyright (C) 2012 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 game.collect;
import static game.collect.Preconditions.checkArgument;
import java.util.EnumMap;
import java.util.Iterator;
/**
* Implementation of {@link ImmutableMap} backed by a non-empty {@link
* java.util.EnumMap}.
*
* @author Louis Wasserman
*/
// we're overriding default serialization
final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
static <K extends Enum<K>, V> ImmutableMap<K, V> asImmutable(EnumMap<K, V> map) {
switch (map.size()) {
case 0:
return ImmutableMap.of();
// case 1: {
// Entry<K, V> entry = Iterables.getOnlyElement(map.entrySet());
// return ImmutableMap.of(entry.getKey(), entry.getValue());
// }
default:
return new ImmutableEnumMap<K, V>(map);
}
}
private transient final EnumMap<K, V> delegate;
private ImmutableEnumMap(EnumMap<K, V> delegate) {
this.delegate = delegate;
checkArgument(!delegate.isEmpty());
}
@Override
ImmutableSet<K> createKeySet() {
return new ImmutableSet<K>() {
@Override
public boolean contains(Object object) {
return delegate.containsKey(object);
}
@Override
public int size() {
return ImmutableEnumMap.this.size();
}
@Override
public UnmodifiableIterator<K> iterator() {
return Iterators.unmodifiableIterator(delegate.keySet().iterator());
}
@Override
boolean isPartialView() {
return true;
}
};
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
@Override
public V get(Object key) {
return delegate.get(key);
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
return new ImmutableMapEntrySet<K, V>() {
@Override
ImmutableMap<K, V> map() {
return ImmutableEnumMap.this;
}
@Override
public UnmodifiableIterator<Entry<K, V>> iterator() {
return new UnmodifiableIterator<Entry<K, V>>() {
private final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
@Override
public boolean hasNext() {
return backingIterator.hasNext();
}
@Override
public Entry<K, V> next() {
Entry<K, V> entry = backingIterator.next();
return Maps.immutableEntry(entry.getKey(), entry.getValue());
}
};
}
};
}
@Override
boolean isPartialView() {
return false;
}
// All callers of the constructor are restricted to <K extends Enum<K>>.
// @Override Object writeReplace() {
// return new EnumSerializedForm<K, V>(delegate);
// }
//
// /*
// * This class is used to serialize ImmutableEnumSet instances.
// */
// private static class EnumSerializedForm<K extends Enum<K>, V>
// implements Serializable {
// final EnumMap<K, V> delegate;
// EnumSerializedForm(EnumMap<K, V> delegate) {
// this.delegate = delegate;
// }
// Object readResolve() {
// return new ImmutableEnumMap<K, V>(delegate);
// }
// private static final long serialVersionUID = 0;
// }
}

View file

@ -1,117 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import java.io.Serializable;
import java.util.Collection;
import java.util.EnumSet;
/**
* Implementation of {@link ImmutableSet} backed by a non-empty {@link
* java.util.EnumSet}.
*
* @author Jared Levy
*/
// we're overriding default serialization
final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
static <E extends Enum<E>> ImmutableSet<E> asImmutable(EnumSet<E> set) {
switch (set.size()) {
case 0:
return ImmutableSet.of();
// case 1:
// return ImmutableSet.of(Iterables.getOnlyElement(set));
default:
return new ImmutableEnumSet<E>(set);
}
}
/*
* Notes on EnumSet and <E extends Enum<E>>:
*
* This class isn't an arbitrary ForwardingImmutableSet because we need to
* know that calling {@code clone()} during deserialization will return an
* object that no one else has a reference to, allowing us to guarantee
* immutability. Hence, we support only {@link EnumSet}.
*/
private final transient EnumSet<E> delegate;
private ImmutableEnumSet(EnumSet<E> delegate) {
this.delegate = delegate;
}
@Override boolean isPartialView() {
return false;
}
@Override public UnmodifiableIterator<E> iterator() {
return Iterators.unmodifiableIterator(delegate.iterator());
}
@Override
public int size() {
return delegate.size();
}
@Override public boolean contains(Object object) {
return delegate.contains(object);
}
@Override public boolean containsAll(Collection<?> collection) {
return delegate.containsAll(collection);
}
@Override public boolean isEmpty() {
return delegate.isEmpty();
}
@Override public boolean equals(Object object) {
return object == this || delegate.equals(object);
}
private transient int hashCode;
@Override public int hashCode() {
int result = hashCode;
return (result == 0) ? hashCode = delegate.hashCode() : result;
}
@Override public String toString() {
return delegate.toString();
}
// All callers of the constructor are restricted to <E extends Enum<E>>.
@Override Object writeReplace() {
return new EnumSerializedForm<E>(delegate);
}
/*
* This class is used to serialize ImmutableEnumSet instances.
*/
private static class EnumSerializedForm<E extends Enum<E>>
implements Serializable {
final EnumSet<E> delegate;
EnumSerializedForm(EnumSet<E> delegate) {
this.delegate = delegate;
}
Object readResolve() {
// EJ2 #76: Write readObject() methods defensively.
return new ImmutableEnumSet<E>(delegate.clone());
}
private static final long serialVersionUID = 0;
}
}

View file

@ -1,743 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.ObjectArrays.arraysCopyOf;
import static game.collect.ObjectArrays.checkElementsNotNull;
import static game.collect.Preconditions.checkElementIndex;
import static game.collect.Preconditions.checkNotNull;
import static game.collect.Preconditions.checkPositionIndexes;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
/**
* A high-performance, immutable, random-access {@code List} implementation.
* Does not permit null elements.
*
* <p>Unlike {@link Collections#unmodifiableList}, which is a <i>view</i> of a
* separate collection that can still change, an instance of {@code
* ImmutableList} contains its own private data and will <i>never</i> change.
* {@code ImmutableList} is convenient for {@code public static final} lists
* ("constant lists") and also lets you easily make a "defensive copy" of a list
* provided to your class by a caller.
*
* <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
* it has no public or protected constructors. Thus, instances of this type are
* guaranteed to be immutable.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @see ImmutableMap
* @see ImmutableSet
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
// we're overriding default serialization
public abstract class ImmutableList<E> extends ImmutableCollection<E>
implements List<E>, RandomAccess {
private static final ImmutableList<Object> EMPTY =
new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
/**
* Returns the empty immutable list. This set behaves and performs comparably
* to {@link Collections#emptyList}, and is preferable mainly for consistency
* and maintainability of your code.
*/
// Casting to any type is safe because the list will never hold any elements.
public static <E> ImmutableList<E> of() {
return (ImmutableList<E>) EMPTY;
}
/**
* Returns an immutable list containing a single element. This list behaves
* and performs comparably to {@link Collections#singleton}, but will not
* accept a null element. It is preferable mainly for consistency and
* maintainability of your code.
*
* @throws NullPointerException if {@code element} is null
*/
// public static <E> ImmutableList<E> of(E element) {
// return new SingletonImmutableList<E>(element);
// }
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(E e1, E e2) {
return construct(e1, e2);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(E e1, E e2, E e3) {
return construct(e1, e2, e3);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) {
return construct(e1, e2, e3, e4);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) {
return construct(e1, e2, e3, e4, e5);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
return construct(e1, e2, e3, e4, e5, e6);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
return construct(e1, e2, e3, e4, e5, e6, e7);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);
}
// These go up to eleven. After that, you just get the varargs form, and
// whatever warnings might come along with it. :(
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any element is null
* @since 3.0 (source-compatible since 2.0)
*/
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12,
E... others) {
Object[] array = new Object[12 + others.length];
array[0] = e1;
array[1] = e2;
array[2] = e3;
array[3] = e4;
array[4] = e5;
array[5] = e6;
array[6] = e7;
array[7] = e8;
array[8] = e9;
array[9] = e10;
array[10] = e11;
array[11] = e12;
System.arraycopy(others, 0, array, 12, others.length);
return construct(array);
}
/**
* Returns an immutable list containing the given elements, in order. If
* {@code elements} is a {@link Collection}, this method behaves exactly as
* {@link #copyOf(Collection)}; otherwise, it behaves exactly as {@code
* copyOf(elements.iterator()}.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {
checkNotNull(elements); // TODO(kevinb): is this here only for GWT?
return (elements instanceof Collection)
? copyOf(Filter.cast(elements))
: copyOf(elements.iterator());
}
/**
* Returns an immutable list containing the given elements, in order.
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*
* <p>Note that if {@code list} is a {@code List<String>}, then {@code
* ImmutableList.copyOf(list)} returns an {@code ImmutableList<String>}
* containing each of the strings in {@code list}, while
* ImmutableList.of(list)} returns an {@code ImmutableList<List<String>>}
* containing one element (the given list itself).
*
* <p>This method is safe to use even when {@code elements} is a synchronized
* or concurrent collection that is currently being modified by another
* thread.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {
if (elements instanceof ImmutableCollection) {
// all supported methods are covariant
ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
return list.isPartialView()
? ImmutableList.<E>asImmutableList(list.toArray())
: list;
}
return construct(elements.toArray());
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) {
// We special-case for 0 or 1 elements, but going further is madness.
if (!elements.hasNext()) {
return of();
}
// E first = elements.next();
// if (!elements.hasNext()) {
// return of(first);
// } else {
return new ImmutableList.Builder<E>()
// .add(first)
.addAll(elements)
.build();
// }
}
/**
* Returns an immutable list containing the given elements, in order.
*
* @throws NullPointerException if any of {@code elements} is null
* @since 3.0
*/
public static <E> ImmutableList<E> copyOf(E[] elements) {
switch (elements.length) {
case 0:
return ImmutableList.of();
// case 1:
// return new SingletonImmutableList<E>(elements[0]);
default:
return new RegularImmutableList<E>(checkElementsNotNull(elements.clone()));
}
}
/**
* Views the array as an immutable list. Checks for nulls; does not copy.
*/
private static <E> ImmutableList<E> construct(Object... elements) {
return asImmutableList(checkElementsNotNull(elements));
}
/**
* Views the array as an immutable list. Does not check for nulls; does not copy.
*
* <p>The array must be internally created.
*/
static <E> ImmutableList<E> asImmutableList(Object[] elements) {
return asImmutableList(elements, elements.length);
}
/**
* Views the array as an immutable list. Copies if the specified range does not cover the complete
* array. Does not check for nulls.
*/
static <E> ImmutableList<E> asImmutableList(Object[] elements, int length) {
switch (length) {
case 0:
return of();
// case 1:
// // collection had only Es in it
// ImmutableList<E> list = new SingletonImmutableList<E>((E) elements[0]);
// return list;
default:
if (length < elements.length) {
elements = arraysCopyOf(elements, length);
}
return new RegularImmutableList<E>(elements);
}
}
ImmutableList() {}
// This declaration is needed to make List.iterator() and
// ImmutableCollection.iterator() consistent.
@Override public UnmodifiableIterator<E> iterator() {
return listIterator();
}
@Override public UnmodifiableListIterator<E> listIterator() {
return listIterator(0);
}
@Override public UnmodifiableListIterator<E> listIterator(int index) {
return new AbstractIndexedListIterator<E>(size(), index) {
@Override
protected E get(int index) {
return ImmutableList.this.get(index);
}
};
}
@Override
public int indexOf(Object object) {
return (object == null) ? -1 : indexOfImpl(this, object);
}
@Override
public int lastIndexOf(Object object) {
return (object == null) ? -1 : lastIndexOfImpl(this, object);
}
@Override
public boolean contains(Object object) {
return indexOf(object) >= 0;
}
// constrain the return type to ImmutableList<E>
/**
* Returns an immutable list of the elements between the specified {@code
* fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code
* fromIndex} and {@code toIndex} are equal, the empty immutable list is
* returned.)
*/
@Override
public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
int length = toIndex - fromIndex;
switch (length) {
case 0:
return of();
// case 1:
// return of(get(fromIndex));
default:
return subListUnchecked(fromIndex, toIndex);
}
}
/**
* Called by the default implementation of {@link #subList} when {@code
* toIndex - fromIndex > 1}, after index validation has already been
* performed.
*/
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
return new SubList(fromIndex, toIndex - fromIndex);
}
class SubList extends ImmutableList<E> {
transient final int offset;
transient final int length;
SubList(int offset, int length) {
this.offset = offset;
this.length = length;
}
@Override
public int size() {
return length;
}
@Override
public E get(int index) {
checkElementIndex(index, length);
return ImmutableList.this.get(index + offset);
}
@Override
public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, length);
return ImmutableList.this.subList(fromIndex + offset, toIndex + offset);
}
@Override
boolean isPartialView() {
return true;
}
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean addAll(int index, Collection<? extends E> newElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final E set(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void add(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final E remove(int index) {
throw new UnsupportedOperationException();
}
/**
* Returns this list instance.
*
* @since 2.0
*/
@Override public final ImmutableList<E> asList() {
return this;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
// this loop is faster for RandomAccess instances, which ImmutableLists are
int size = size();
for (int i = 0; i < size; i++) {
dst[offset + i] = get(i);
}
return offset + size;
}
/**
* Returns a view of this immutable list in reverse order. For example, {@code
* ImmutableList.of(1, 2, 3).reverse()} is equivalent to {@code
* ImmutableList.of(3, 2, 1)}.
*
* @return a view of this immutable list in reverse order
* @since 7.0
*/
public ImmutableList<E> reverse() {
return new ReverseImmutableList<E>(this);
}
private static class ReverseImmutableList<E> extends ImmutableList<E> {
private final transient ImmutableList<E> forwardList;
ReverseImmutableList(ImmutableList<E> backingList) {
this.forwardList = backingList;
}
private int reverseIndex(int index) {
return (size() - 1) - index;
}
private int reversePosition(int index) {
return size() - index;
}
@Override public ImmutableList<E> reverse() {
return forwardList;
}
@Override public boolean contains(Object object) {
return forwardList.contains(object);
}
@Override public int indexOf(Object object) {
int index = forwardList.lastIndexOf(object);
return (index >= 0) ? reverseIndex(index) : -1;
}
@Override public int lastIndexOf(Object object) {
int index = forwardList.indexOf(object);
return (index >= 0) ? reverseIndex(index) : -1;
}
@Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
return forwardList.subList(
reversePosition(toIndex), reversePosition(fromIndex)).reverse();
}
@Override public E get(int index) {
checkElementIndex(index, size());
return forwardList.get(reverseIndex(index));
}
@Override public int size() {
return forwardList.size();
}
@Override boolean isPartialView() {
return forwardList.isPartialView();
}
}
/**
* An implementation of {@link List#equals(Object)}.
*/
static boolean equalsImpl(List<?> list, Object object) {
if (object == checkNotNull(list)) {
return true;
}
if (!(object instanceof List)) {
return false;
}
List<?> o = (List<?>) object;
return list.size() == o.size()
&& Iterators.elementsEqual(list.iterator(), o.iterator());
}
/**
* An implementation of {@link List#indexOf(Object)}.
*/
static int indexOfImpl(List<?> list, Object element) {
ListIterator<?> listIterator = list.listIterator();
while (listIterator.hasNext()) {
if (Preconditions.equal(element, listIterator.next())) {
return listIterator.previousIndex();
}
}
return -1;
}
/**
* An implementation of {@link List#lastIndexOf(Object)}.
*/
static int lastIndexOfImpl(List<?> list, Object element) {
ListIterator<?> listIterator = list.listIterator(list.size());
while (listIterator.hasPrevious()) {
if (Preconditions.equal(element, listIterator.previous())) {
return listIterator.nextIndex();
}
}
return -1;
}
@Override public boolean equals(Object obj) {
return equalsImpl(this, obj);
}
@Override public int hashCode() {
int hashCode = 1;
int n = size();
for (int i = 0; i < n; i++) {
hashCode = 31 * hashCode + get(i).hashCode();
hashCode = ~~hashCode;
// needed to deal with GWT integer overflow
}
return hashCode;
}
/*
* Serializes ImmutableLists as their logical contents. This ensures that
* implementation types do not leak into the serialized representation.
*/
static class SerializedForm implements Serializable {
final Object[] elements;
SerializedForm(Object[] elements) {
this.elements = elements;
}
Object readResolve() {
return copyOf(elements);
}
private static final long serialVersionUID = 0;
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
@Override Object writeReplace() {
return new SerializedForm(toArray());
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static <E> Builder<E> builder() {
return new Builder<E>();
}
/**
* A builder for creating immutable list instances, especially {@code public
* static final} lists ("constant lists"). Example: <pre> {@code
*
* public static final ImmutableList<Color> GOOGLE_COLORS
* = new ImmutableList.Builder<Color>()
* .addAll(WEBSAFE_COLORS)
* .add(new Color(0, 191, 255))
* .build();}</pre>
*
* <p>Builder instances can be reused; it is safe to call {@link #build} multiple
* times to build multiple lists in series. Each new list contains all the
* elements of the ones created before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
public static final class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableList#builder}.
*/
public Builder() {
this(DEFAULT_INITIAL_CAPACITY);
}
// TODO(user): consider exposing this
Builder(int capacity) {
super(capacity);
}
/**
* Adds {@code element} to the {@code ImmutableList}.
*
* @param element the element to add
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
@Override public Builder<E> add(E element) {
super.add(element);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableList}.
*
* @param elements the {@code Iterable} to add to the {@code ImmutableList}
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableList}.
*
* @param elements the {@code Iterable} to add to the {@code ImmutableList}
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableList}.
*
* @param elements the {@code Iterable} to add to the {@code ImmutableList}
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
/**
* Returns a newly-created {@code ImmutableList} based on the contents of
* the {@code Builder}.
*/
@Override public ImmutableList<E> build() {
return asImmutableList(contents, size);
}
}
}

View file

@ -1,548 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.CollectPreconditions.checkEntryNotNull;
import java.io.Serializable;
import java.util.EnumMap;
import java.util.Map;
import game.collect.ImmutableMapEntry.TerminalEntry;
/**
* An immutable, hash-based {@link Map} with reliable user-specified iteration
* order. Does not permit null keys or values.
*
* <p>Unlike {@link Collections#unmodifiableMap}, which is a <i>view</i> of a
* separate map which can still change, an instance of {@code ImmutableMap}
* contains its own data and will <i>never</i> change. {@code ImmutableMap} is
* convenient for {@code public static final} maps ("constant maps") and also
* lets you easily make a "defensive copy" of a map provided to your class by a
* caller.
*
* <p><i>Performance notes:</i> unlike {@link HashMap}, {@code ImmutableMap} is
* not optimized for element types that have slow {@link Object#equals} or
* {@link Object#hashCode} implementations. You can get better performance by
* having your element type cache its own hash codes, and by making use of the
* cached values to short-circuit a slow {@code equals} algorithm.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
// // we're overriding default serialization
public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
/**
* Returns the empty map. This map behaves and performs comparably to
* {@link Collections#emptyMap}, and is preferable mainly for consistency
* and maintainability of your code.
*/
public static <K, V> ImmutableMap<K, V> of() {
return (ImmutableMap<K, V>)EmptyImmutableMap.INSTANCE;
}
/**
* Returns an immutable map containing a single entry. This map behaves and
* performs comparably to {@link Collections#singletonMap} but will not accept
* a null key or value. It is preferable mainly for consistency and
* maintainability of your code.
*/
// public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {
// return ImmutableBiMap.of(k1, v1);
// }
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
return new RegularImmutableMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
public static <K, V> ImmutableMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3) {
return new RegularImmutableMap<K, V>(
entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
public static <K, V> ImmutableMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return new RegularImmutableMap<K, V>(
entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
public static <K, V> ImmutableMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
return new RegularImmutableMap<K, V>(entryOf(k1, v1),
entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
}
// looking for of() with > 5 entries? Use the builder instead.
/**
* Verifies that {@code key} and {@code value} are non-null, and returns a new
* immutable entry with those values.
*
* <p>A call to {@link Map.Entry#setValue} on the returned entry will always
* throw {@link UnsupportedOperationException}.
*/
static <K, V> TerminalEntry<K, V> entryOf(K key, V value) {
checkEntryNotNull(key, value);
return new TerminalEntry<K, V>(key, value);
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static <K, V> Builder<K, V> builder() {
return new Builder<K, V>();
}
static void checkNoConflict(boolean safe, String conflictDescription,
Entry<?, ?> entry1, Entry<?, ?> entry2) {
if (!safe) {
throw new IllegalArgumentException(
"Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2);
}
}
/**
* A builder for creating immutable map instances, especially {@code public
* static final} maps ("constant maps"). Example: <pre> {@code
*
* static final ImmutableMap<String, Integer> WORD_TO_INT =
* new ImmutableMap.Builder<String, Integer>()
* .put("one", 1)
* .put("two", 2)
* .put("three", 3)
* .build();}</pre>
*
* <p>For <i>small</i> immutable maps, the {@code ImmutableMap.of()} methods are
* even more convenient.
*
* <p>Builder instances can be reused - it is safe to call {@link #build}
* multiple times to build multiple maps in series. Each map is a superset of
* the maps created before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
public static class Builder<K, V> {
TerminalEntry<K, V>[] entries;
int size;
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableMap#builder}.
*/
public Builder() {
this(ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY);
}
Builder(int initialCapacity) {
this.entries = new TerminalEntry[initialCapacity];
this.size = 0;
}
private void ensureCapacity(int minCapacity) {
if (minCapacity > entries.length) {
entries = ObjectArrays.arraysCopyOf(
entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
}
}
/**
* Associates {@code key} with {@code value} in the built map. Duplicate
* keys are not allowed, and will cause {@link #build} to fail.
*/
public Builder<K, V> put(K key, V value) {
ensureCapacity(size + 1);
TerminalEntry<K, V> entry = entryOf(key, value);
// don't inline this: we want to fail atomically if key or value is null
entries[size++] = entry;
return this;
}
/**
* Adds the given {@code entry} to the map, making it immutable if
* necessary. Duplicate keys are not allowed, and will cause {@link #build}
* to fail.
*
* @since 11.0
*/
public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
return put(entry.getKey(), entry.getValue());
}
/**
* Associates all of the given map's keys and values in the built map.
* Duplicate keys are not allowed, and will cause {@link #build} to fail.
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
ensureCapacity(size + map.size());
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry);
}
return this;
}
/*
* TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap
* versions throw an IllegalStateException instead?
*/
/**
* Returns a newly-created immutable map.
*
* @throws IllegalArgumentException if duplicate keys were added
*/
public ImmutableMap<K, V> build() {
switch (size) {
case 0:
return of();
// case 1:
// return of(entries[0].getKey(), entries[0].getValue());
default:
return new RegularImmutableMap<K, V>(size, entries);
}
}
}
/**
* Returns an immutable map containing the same entries as {@code map}. If
* {@code map} somehow contains entries with duplicate keys (for example, if
* it is a {@code SortedMap} whose comparator is not <i>consistent with
* equals</i>), the results of this method are undefined.
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
public static <K, V> ImmutableMap<K, V> copyOf(
Map<? extends K, ? extends V> map) {
if ((map instanceof ImmutableMap)) { // && !(map instanceof ImmutableSortedMap)) {
// TODO(user): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
// on the ImmutableMap delegate(), rather than the bimap itself
// safe since map is not writable
ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) map;
if (!kvMap.isPartialView()) {
return kvMap;
}
} else if (map instanceof EnumMap) {
return copyOfEnumMapUnsafe(map);
}
Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
switch (entries.length) {
case 0:
return of();
// case 1:
// // all entries will be Entry<K, V>'s
// Entry<K, V> onlyEntry = (Entry<K, V>) entries[0];
// return of(onlyEntry.getKey(), onlyEntry.getValue());
default:
return new RegularImmutableMap<K, V>(entries);
}
}
// If the map is an EnumMap, it must have key type K for some <K extends Enum<K>>.
private static <K, V> ImmutableMap<K, V> copyOfEnumMapUnsafe(Map<? extends K, ? extends V> map) {
return copyOfEnumMap((EnumMap) map);
}
private static <K extends Enum<K>, V> ImmutableMap<K, V> copyOfEnumMap(
Map<K, ? extends V> original) {
EnumMap<K, V> copy = new EnumMap<K, V>(original);
for (Map.Entry<?, ?> entry : copy.entrySet()) {
checkEntryNotNull(entry.getKey(), entry.getValue());
}
return ImmutableEnumMap.asImmutable(copy);
}
private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
ImmutableMap() {}
/**
* Guaranteed to throw an exception and leave the map unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final V put(K k, V v) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the map unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final V remove(Object o) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the map unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void putAll(Map<? extends K, ? extends V> map) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the map unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean containsKey(Object key) {
return get(key) != null;
}
@Override
public boolean containsValue(Object value) {
return values().contains(value);
}
// Overriding to mark it Nullable
@Override
public abstract V get(Object key);
private transient ImmutableSet<Entry<K, V>> entrySet;
/**
* Returns an immutable set of the mappings in this map. The entries are in
* the same order as the parameters used to build this map.
*/
@Override
public ImmutableSet<Entry<K, V>> entrySet() {
ImmutableSet<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
abstract ImmutableSet<Entry<K, V>> createEntrySet();
private transient ImmutableSet<K> keySet;
/**
* Returns an immutable set of the keys in this map. These keys are in
* the same order as the parameters used to build this map.
*/
@Override
public ImmutableSet<K> keySet() {
ImmutableSet<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
ImmutableSet<K> createKeySet() {
return new ImmutableMapKeySet<K, V>(this);
}
private transient ImmutableCollection<V> values;
/**
* Returns an immutable collection of the values in this map. The values are
* in the same order as the parameters used to build this map.
*/
@Override
public ImmutableCollection<V> values() {
ImmutableCollection<V> result = values;
return (result == null) ? values = new ImmutableMapValues<K, V>(this) : result;
}
// cached so that this.multimapView().inverse() only computes inverse once
// private transient ImmutableSetMultimap<K, V> multimapView;
/**
* Returns a multimap view of the map.
*
* @since 14.0
*/
// @Beta
// public ImmutableSetMultimap<K, V> asMultimap() {
// ImmutableSetMultimap<K, V> result = multimapView;
// return (result == null) ? (multimapView = createMultimapView()) : result;
// }
//
// private ImmutableSetMultimap<K, V> createMultimapView() {
// ImmutableMap<K, ImmutableSet<V>> map = viewMapValuesAsSingletonSets();
// return new ImmutableSetMultimap<K, V>(map, map.size(), null);
// }
// private ImmutableMap<K, ImmutableSet<V>> viewMapValuesAsSingletonSets() {
// return new MapViewOfValuesAsSingletonSets<K, V>(this);
// }
//
// private static final class MapViewOfValuesAsSingletonSets<K, V>
// extends ImmutableMap<K, ImmutableSet<V>> {
// private final ImmutableMap<K, V> delegate;
//
// MapViewOfValuesAsSingletonSets(ImmutableMap<K, V> delegate) {
// this.delegate = checkNotNull(delegate);
// }
//
// @Override public int size() {
// return delegate.size();
// }
//
// @Override public boolean containsKey(Object key) {
// return delegate.containsKey(key);
// }
//
// @Override public ImmutableSet<V> get(Object key) {
// V outerValue = delegate.get(key);
// return (outerValue == null) ? null : ImmutableSet.of(outerValue);
// }
//
// @Override boolean isPartialView() {
// return false;
// }
//
// @Override ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
// return new ImmutableMapEntrySet<K, ImmutableSet<V>>() {
// @Override ImmutableMap<K, ImmutableSet<V>> map() {
// return MapViewOfValuesAsSingletonSets.this;
// }
//
// @Override
// public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
// final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
// return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
// @Override public boolean hasNext() {
// return backingIterator.hasNext();
// }
//
// @Override public Entry<K, ImmutableSet<V>> next() {
// final Entry<K, V> backingEntry = backingIterator.next();
// return new AbstractMapEntry<K, ImmutableSet<V>>() {
// @Override public K getKey() {
// return backingEntry.getKey();
// }
//
// @Override public ImmutableSet<V> getValue() {
// return ImmutableSet.of(backingEntry.getValue());
// }
// };
// }
// };
// }
// };
// }
// }
@Override public boolean equals(Object object) {
return Maps.equalsImpl(this, object);
}
abstract boolean isPartialView();
@Override public int hashCode() {
// not caching hash code since it could change if map values are mutable
// in a way that modifies their hash codes
return entrySet().hashCode();
}
// @Override public String toString() {
// return Maps.toStringImpl(this);
// }
/**
* Serialized type for all ImmutableMap instances. It captures the logical
* contents and they are reconstructed using public factory methods. This
* ensures that the implementation types remain as implementation details.
*/
// static class SerializedForm implements Serializable {
// private final Object[] keys;
// private final Object[] values;
// SerializedForm(ImmutableMap<?, ?> map) {
// keys = new Object[map.size()];
// values = new Object[map.size()];
// int i = 0;
// for (Entry<?, ?> entry : map.entrySet()) {
// keys[i] = entry.getKey();
// values[i] = entry.getValue();
// i++;
// }
// }
// Object readResolve() {
// Builder<Object, Object> builder = new Builder<Object, Object>();
// return createMap(builder);
// }
// Object createMap(Builder<Object, Object> builder) {
// for (int i = 0; i < keys.length; i++) {
// builder.put(keys[i], values[i]);
// }
// return builder.build();
// }
// private static final long serialVersionUID = 0;
// }
//
// Object writeReplace() {
// return new SerializedForm(this);
// }
}

View file

@ -1,68 +0,0 @@
/*
* Copyright (C) 2013 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 game.collect;
import static game.collect.CollectPreconditions.checkEntryNotNull;
/**
* Implementation of {@code Map.Entry} for {@link ImmutableMap} that adds extra methods to traverse
* hash buckets for the key and the value. This allows reuse in {@link RegularImmutableMap} and
* {@link RegularImmutableBiMap}, which don't have to recopy the entries created by their
* {@code Builder} implementations.
*
* @author Louis Wasserman
*/
abstract class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
ImmutableMapEntry(K key, V value) {
super(key, value);
checkEntryNotNull(key, value);
}
ImmutableMapEntry(ImmutableMapEntry<K, V> contents) {
super(contents.getKey(), contents.getValue());
// null check would be redundant
}
abstract ImmutableMapEntry<K, V> getNextInKeyBucket();
abstract ImmutableMapEntry<K, V> getNextInValueBucket();
static final class TerminalEntry<K, V> extends ImmutableMapEntry<K, V> {
TerminalEntry(ImmutableMapEntry<K, V> contents) {
super(contents);
}
TerminalEntry(K key, V value) {
super(key, value);
}
@Override
ImmutableMapEntry<K, V> getNextInKeyBucket() {
return null;
}
@Override
ImmutableMapEntry<K, V> getNextInValueBucket() {
return null;
}
}
}

View file

@ -1,71 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.io.Serializable;
import java.util.Map.Entry;
/**
* {@code entrySet()} implementation for {@link ImmutableMap}.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
*/
abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
ImmutableMapEntrySet() {}
abstract ImmutableMap<K, V> map();
@Override
public int size() {
return map().size();
}
@Override
public boolean contains(Object object) {
if (object instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) object;
V value = map().get(entry.getKey());
return value != null && value.equals(entry.getValue());
}
return false;
}
@Override
boolean isPartialView() {
return map().isPartialView();
}
@Override
Object writeReplace() {
return new EntrySetSerializedForm<K, V>(map());
}
private static class EntrySetSerializedForm<K, V> implements Serializable {
final ImmutableMap<K, V> map;
EntrySetSerializedForm(ImmutableMap<K, V> map) {
this.map = map;
}
Object readResolve() {
return map.entrySet();
}
private static final long serialVersionUID = 0;
}
}

View file

@ -1,90 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.io.Serializable;
import java.util.Map.Entry;
/**
* {@code keySet()} implementation for {@link ImmutableMap}.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
*/
final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
private final ImmutableMap<K, V> map;
ImmutableMapKeySet(ImmutableMap<K, V> map) {
this.map = map;
}
@Override
public int size() {
return map.size();
}
@Override
public UnmodifiableIterator<K> iterator() {
return asList().iterator();
}
@Override
public boolean contains(Object object) {
return map.containsKey(object);
}
@Override
ImmutableList<K> createAsList() {
final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
return new ImmutableAsList<K>() {
@Override
public K get(int index) {
return entryList.get(index).getKey();
}
@Override
ImmutableCollection<K> delegateCollection() {
return ImmutableMapKeySet.this;
}
};
}
@Override
boolean isPartialView() {
return true;
}
@Override Object writeReplace() {
return new KeySetSerializedForm<K>(map);
}
private static class KeySetSerializedForm<K> implements Serializable {
final ImmutableMap<K, ?> map;
KeySetSerializedForm(ImmutableMap<K, ?> map) {
this.map = map;
}
Object readResolve() {
return map.keySet();
}
private static final long serialVersionUID = 0;
}
}

View file

@ -1,88 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.io.Serializable;
import java.util.Map.Entry;
/**
* {@code values()} implementation for {@link ImmutableMap}.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
*/
final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
private final ImmutableMap<K, V> map;
ImmutableMapValues(ImmutableMap<K, V> map) {
this.map = map;
}
@Override
public int size() {
return map.size();
}
@Override
public UnmodifiableIterator<V> iterator() {
return Maps.valueIterator(map.entrySet().iterator());
}
@Override
public boolean contains(Object object) {
return object != null && Iterators.contains(iterator(), object);
}
@Override
boolean isPartialView() {
return true;
}
@Override
ImmutableList<V> createAsList() {
final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
return new ImmutableAsList<V>() {
@Override
public V get(int index) {
return entryList.get(index).getValue();
}
@Override
ImmutableCollection<V> delegateCollection() {
return ImmutableMapValues.this;
}
};
}
@Override Object writeReplace() {
return new SerializedForm<V>(map);
}
private static class SerializedForm<V> implements Serializable {
final ImmutableMap<?, V> map;
SerializedForm(ImmutableMap<?, V> map) {
this.map = map;
}
Object readResolve() {
return map.values();
}
private static final long serialVersionUID = 0;
}
}

View file

@ -1,533 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import static game.collect.ObjectArrays.checkElementNotNull;
import static game.collect.Preconditions.checkArgument;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
/**
* A high-performance, immutable {@code Set} with reliable, user-specified
* iteration order. Does not permit null elements.
*
* <p>Unlike {@link Collections#unmodifiableSet}, which is a <i>view</i> of a
* separate collection that can still change, an instance of this class contains
* its own private data and will <i>never</i> change. This class is convenient
* for {@code public static final} sets ("constant sets") and also lets you
* easily make a "defensive copy" of a set provided to your class by a caller.
*
* <p><b>Warning:</b> Like most sets, an {@code ImmutableSet} will not function
* correctly if an element is modified after being placed in the set. For this
* reason, and to avoid general confusion, it is strongly recommended to place
* only immutable objects into this collection.
*
* <p>This class has been observed to perform significantly better than {@link
* HashSet} for objects with very fast {@link Object#hashCode} implementations
* (as a well-behaved immutable object should). While this class's factory
* methods create hash-based instances, the {@link ImmutableSortedSet} subclass
* performs binary searches instead.
*
* <p><b>Note:</b> Although this class is not final, it cannot be subclassed
* outside its package as it has no public or protected constructors. Thus,
* instances of this type are guaranteed to be immutable.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @see ImmutableList
* @see ImmutableMap
* @author Kevin Bourrillion
* @author Nick Kralevich
* @since 2.0 (imported from Google Collections Library)
*/
// we're overriding default serialization
public abstract class ImmutableSet<E> extends ImmutableCollection<E>
implements Set<E> {
/**
* Returns the empty immutable set. This set behaves and performs comparably
* to {@link Collections#emptySet}, and is preferable mainly for consistency
* and maintainability of your code.
*/
// Casting to any type is safe because the set will never hold any elements.
public static <E> ImmutableSet<E> of() {
return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE;
}
/**
* Returns an immutable set containing a single element. This set behaves and
* performs comparably to {@link Collections#singleton}, but will not accept
* a null element. It is preferable mainly for consistency and
* maintainability of your code.
*/
// public static <E> ImmutableSet<E> of(E element) {
// return new SingletonImmutableSet<E>(element);
// }
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableSet<E> of(E e1, E e2) {
return construct(2, e1, e2);
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3) {
return construct(3, e1, e2, e3);
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) {
return construct(4, e1, e2, e3, e4);
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any element is null
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) {
return construct(5, e1, e2, e3, e4, e5);
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any element is null
* @since 3.0 (source-compatible since 2.0)
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6,
E... others) {
final int paramCount = 6;
Object[] elements = new Object[paramCount + others.length];
elements[0] = e1;
elements[1] = e2;
elements[2] = e3;
elements[3] = e4;
elements[4] = e5;
elements[5] = e6;
System.arraycopy(others, 0, elements, paramCount, others.length);
return construct(elements.length, elements);
}
/**
* Constructs an {@code ImmutableSet} from the first {@code n} elements of the specified array.
* If {@code k} is the size of the returned {@code ImmutableSet}, then the unique elements of
* {@code elements} will be in the first {@code k} positions, and {@code elements[i] == null} for
* {@code k <= i < n}.
*
* <p>This may modify {@code elements}. Additionally, if {@code n == elements.length} and
* {@code elements} contains no duplicates, {@code elements} may be used without copying in the
* returned {@code ImmutableSet}, in which case it may no longer be modified.
*
* <p>{@code elements} may contain only values of type {@code E}.
*
* @throws NullPointerException if any of the first {@code n} elements of {@code elements} is
* null
*/
private static <E> ImmutableSet<E> construct(int n, Object... elements) {
switch (n) {
case 0:
return of();
// case 1:
// // safe; elements contains only E's
// E elem = (E) elements[0];
// return of(elem);
default:
// continue below to handle the general case
}
int tableSize = chooseTableSize(n);
Object[] table = new Object[tableSize];
int mask = tableSize - 1;
int hashCode = 0;
int uniques = 0;
for (int i = 0; i < n; i++) {
Object element = checkElementNotNull(elements[i], i);
int hash = element.hashCode();
for (int j = Hashing.smear(hash); ; j++) {
int index = j & mask;
Object value = table[index];
if (value == null) {
// Came to an empty slot. Put the element here.
elements[uniques++] = element;
table[index] = element;
hashCode += hash;
break;
} else if (value.equals(element)) {
break;
}
}
}
Arrays.fill(elements, uniques, n, null);
// if (uniques == 1) {
// // There is only one element or elements are all duplicates
// // we are careful to only pass in E
// E element = (E) elements[0];
// return new SingletonImmutableSet<E>(element, hashCode);
// } else
if (tableSize != chooseTableSize(uniques)) {
// Resize the table when the array includes too many duplicates.
// when this happens, we have already made a copy
return construct(uniques, elements);
} else {
Object[] uniqueElements = (uniques < elements.length)
? ObjectArrays.arraysCopyOf(elements, uniques)
: elements;
return new RegularImmutableSet<E>(uniqueElements, hashCode, table, mask);
}
}
// We use power-of-2 tables, and this is the highest int that's a power of 2
static final int MAX_TABLE_SIZE = 1 << (Integer.SIZE - 2);
// Represents how tightly we can pack things, as a maximum.
private static final double DESIRED_LOAD_FACTOR = 0.7;
// If the set has this many elements, it will "max out" the table size
private static final int CUTOFF =
(int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR);
/**
* Returns an array size suitable for the backing array of a hash table that
* uses open addressing with linear probing in its implementation. The
* returned size is the smallest power of two that can hold setSize elements
* with the desired load factor.
*
* <p>Do not call this method with setSize < 2.
*/
// @VisibleForTesting
static int chooseTableSize(int setSize) {
setSize = setSize < 2 ? 2 : setSize;
// Correct the size for open addressing to match desired load factor.
if (setSize < CUTOFF) {
// Round up to the next highest power of 2.
int tableSize = Integer.highestOneBit(setSize - 1) << 1;
while (tableSize * DESIRED_LOAD_FACTOR < setSize) {
tableSize <<= 1;
}
return tableSize;
}
// The table can't be completely full or we'll get infinite reprobes
checkArgument(setSize < MAX_TABLE_SIZE, "collection too large");
return MAX_TABLE_SIZE;
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any of {@code elements} is null
* @since 3.0
*/
public static <E> ImmutableSet<E> copyOf(E[] elements) {
switch (elements.length) {
case 0:
return of();
// case 1:
// return of(elements[0]);
default:
return construct(elements.length, elements.clone());
}
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored. This method iterates over {@code elements} at most once.
*
* <p>Note that if {@code s} is a {@code Set<String>}, then {@code
* ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
* each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
* a {@code ImmutableSet<Set<String>>} containing one element (the given set
* itself).
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) {
return (elements instanceof Collection)
? copyOf(Filter.cast(elements))
: copyOf(elements.iterator());
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableSet<E> copyOf(Iterator<? extends E> elements) {
// We special-case for 0 or 1 elements, but anything further is madness.
if (!elements.hasNext()) {
return of();
}
// E first = elements.next();
// if (!elements.hasNext()) {
// return of(first);
// } else {
return new ImmutableSet.Builder<E>()
// .add(first)
.addAll(elements)
.build();
// }
}
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored. This method iterates over {@code elements} at most
* once.
*
* <p>Note that if {@code s} is a {@code Set<String>}, then {@code
* ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
* each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
* a {@code ImmutableSet<Set<String>>} containing one element (the given set
* itself).
*
* <p><b>Note:</b> Despite what the method name suggests, {@code copyOf} will
* return constant-space views, rather than linear-space copies, of some
* inputs known to be immutable. For some other immutable inputs, such as key
* sets of an {@code ImmutableMap}, it still performs a copy in order to avoid
* holding references to the values of the map. The heuristics used in this
* decision are undocumented and subject to change except that:
* <ul>
* <li>A full copy will be done of any {@code ImmutableSortedSet}.</li>
* <li>{@code ImmutableSet.copyOf()} is idempotent with respect to pointer
* equality.</li>
* </ul>
*
* <p>This method is safe to use even when {@code elements} is a synchronized
* or concurrent collection that is currently being modified by another
* thread.
*
* @throws NullPointerException if any of {@code elements} is null
* @since 7.0 (source-compatible since 2.0)
*/
public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
/*
* TODO(user): consider checking for ImmutableAsList here
* TODO(user): consider checking for Multiset here
*/
if (elements instanceof ImmutableSet) {
// && !(elements instanceof ImmutableSortedSet)) {
// all supported methods are covariant
ImmutableSet<E> set = (ImmutableSet<E>) elements;
if (!set.isPartialView()) {
return set;
}
} else if (elements instanceof EnumSet) {
return copyOfEnumSet((EnumSet) elements);
}
Object[] array = elements.toArray();
return construct(array.length, array);
}
private static <E extends Enum<E>> ImmutableSet<E> copyOfEnumSet(
EnumSet<E> enumSet) {
return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet));
}
ImmutableSet() {}
/** Returns {@code true} if the {@code hashCode()} method runs quickly. */
boolean isHashCodeFast() {
return false;
}
@Override public boolean equals(Object object) {
if (object == this) {
return true;
} else if (object instanceof ImmutableSet
&& isHashCodeFast()
&& ((ImmutableSet<?>) object).isHashCodeFast()
&& hashCode() != object.hashCode()) {
return false;
}
return Sets.equalsImpl(this, object);
}
@Override public int hashCode() {
return Sets.hashCodeImpl(this);
}
// This declaration is needed to make Set.iterator() and
// ImmutableCollection.iterator() consistent.
@Override public abstract UnmodifiableIterator<E> iterator();
/*
* This class is used to serialize all ImmutableSet instances, except for
* ImmutableEnumSet/ImmutableSortedSet, regardless of implementation type. It
* captures their "logical contents" and they are reconstructed using public
* static factories. This is necessary to ensure that the existence of a
* particular implementation type is an implementation detail.
*/
private static class SerializedForm implements Serializable {
final Object[] elements;
SerializedForm(Object[] elements) {
this.elements = elements;
}
Object readResolve() {
return copyOf(elements);
}
private static final long serialVersionUID = 0;
}
@Override Object writeReplace() {
return new SerializedForm(toArray());
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static <E> Builder<E> builder() {
return new Builder<E>();
}
/**
* A builder for creating immutable set instances, especially {@code public
* static final} sets ("constant sets"). Example: <pre> {@code
*
* public static final ImmutableSet<Color> GOOGLE_COLORS =
* new ImmutableSet.Builder<Color>()
* .addAll(WEBSAFE_COLORS)
* .add(new Color(0, 191, 255))
* .build();}</pre>
*
* <p>Builder instances can be reused; it is safe to call {@link #build} multiple
* times to build multiple sets in series. Each set is a superset of the set
* created before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
public static class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableSet#builder}.
*/
public Builder() {
this(DEFAULT_INITIAL_CAPACITY);
}
Builder(int capacity) {
super(capacity);
}
/**
* Adds {@code element} to the {@code ImmutableSet}. If the {@code
* ImmutableSet} already contains {@code element}, then {@code add} has no
* effect (only the previously added element is retained).
*
* @param element the element to add
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
@Override public Builder<E> add(E element) {
super.add(element);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableSet},
* ignoring duplicate elements (only the first duplicate element is added).
*
* @param elements the elements to add
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableSet},
* ignoring duplicate elements (only the first duplicate element is added).
*
* @param elements the {@code Iterable} to add to the {@code ImmutableSet}
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableSet},
* ignoring duplicate elements (only the first duplicate element is added).
*
* @param elements the elements to add to the {@code ImmutableSet}
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
@Override public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
/**
* Returns a newly-created {@code ImmutableSet} based on the contents of
* the {@code Builder}.
*/
@Override public ImmutableSet<E> build() {
ImmutableSet<E> result = construct(size, contents);
// construct has the side effect of deduping contents, so we update size
// accordingly.
size = result.size();
return result;
}
}
}

View file

@ -1,436 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import static game.collect.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* An immutable {@link Table} with reliable user-specified iteration order.
* Does not permit null keys or values.
*
* <p><b>Note</b>: Although this class is not final, it cannot be subclassed as
* it has no public or protected constructors. Thus, instances of this class are
* guaranteed to be immutable.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Gregory Kick
* @since 11.0
*/
// TODO(gak): make serializable
public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
private static final ImmutableTable<Object, Object, Object> EMPTY
= new SparseImmutableTable<Object, Object, Object>(
ImmutableList.<Cell<Object, Object, Object>>of(),
ImmutableSet.of(), ImmutableSet.of());
/** Returns an empty immutable table. */
public static <R, C, V> ImmutableTable<R, C, V> of() {
return (ImmutableTable<R, C, V>) EMPTY;
}
// /** Returns an immutable table containing a single cell. */
// public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey,
// C columnKey, V value) {
// return new SingletonImmutableTable<R, C, V>(rowKey, columnKey, value);
// }
/**
* Returns an immutable copy of the provided table.
*
* <p>The {@link Table#cellSet()} iteration order of the provided table
* determines the iteration ordering of all views in the returned table. Note
* that some views of the original table and the copied table may have
* different iteration orders. For more control over the ordering, create a
* {@link Builder} and call {@link Builder#orderRowsBy},
* {@link Builder#orderColumnsBy}, and {@link Builder#putAll}
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*/
public static <R, C, V> ImmutableTable<R, C, V> copyOf(
Table<? extends R, ? extends C, ? extends V> table) {
if (table instanceof ImmutableTable) {
ImmutableTable<R, C, V> parameterizedTable
= (ImmutableTable<R, C, V>) table;
return parameterizedTable;
} else {
int size = table.size();
switch (size) {
case 0:
return of();
// case 1:
// Cell<? extends R, ? extends C, ? extends V> onlyCell
// = Iterables.getOnlyElement(table.cellSet());
// return ImmutableTable.<R, C, V>of(onlyCell.getRowKey(),
// onlyCell.getColumnKey(), onlyCell.getValue());
default:
ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder
= ImmutableSet.builder();
for (Cell<? extends R, ? extends C, ? extends V> cell :
table.cellSet()) {
/*
* Must cast to be able to create a Cell<R, C, V> rather than a
* Cell<? extends R, ? extends C, ? extends V>
*/
cellSetBuilder.add(cellOf((R) cell.getRowKey(),
(C) cell.getColumnKey(), (V) cell.getValue()));
}
return RegularImmutableTable.forCells(cellSetBuilder.build());
}
}
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder#ImmutableTable.Builder()} constructor.
*/
// public static <R, C, V> Builder<R, C, V> builder() {
// return new Builder<R, C, V>();
// }
public static <R, C, V> Cell<R, C, V> immutableCell(
R rowKey, C columnKey, V value) {
return new ImmutableCell<R, C, V>(rowKey, columnKey, value);
}
static final class ImmutableCell<R, C, V>
extends AbstractCell<R, C, V> implements Serializable {
private final R rowKey;
private final C columnKey;
private final V value;
ImmutableCell(
R rowKey, C columnKey, V value) {
this.rowKey = rowKey;
this.columnKey = columnKey;
this.value = value;
}
@Override
public R getRowKey() {
return rowKey;
}
@Override
public C getColumnKey() {
return columnKey;
}
@Override
public V getValue() {
return value;
}
private static final long serialVersionUID = 0;
}
abstract static class AbstractCell<R, C, V> implements Cell<R, C, V> {
// needed for serialization
AbstractCell() {}
@Override public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Cell) {
Cell<?, ?, ?> other = (Cell<?, ?, ?>) obj;
return Preconditions.equal(getRowKey(), other.getRowKey())
&& Preconditions.equal(getColumnKey(), other.getColumnKey())
&& Preconditions.equal(getValue(), other.getValue());
}
return false;
}
@Override public int hashCode() {
return Arrays.hashCode(new Object[] {getRowKey(), getColumnKey(), getValue()});
}
@Override public String toString() {
return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue();
}
}
/**
* Verifies that {@code rowKey}, {@code columnKey} and {@code value} are
* non-null, and returns a new entry with those values.
*/
static <R, C, V> Cell<R, C, V> cellOf(R rowKey, C columnKey, V value) {
return immutableCell(checkNotNull(rowKey), checkNotNull(columnKey),
checkNotNull(value));
}
/**
* A builder for creating immutable table instances, especially {@code public
* static final} tables ("constant tables"). Example: <pre> {@code
*
* static final ImmutableTable<Integer, Character, String> SPREADSHEET =
* new ImmutableTable.Builder<Integer, Character, String>()
* .put(1, 'A', "foo")
* .put(1, 'B', "bar")
* .put(2, 'A', "baz")
* .build();}</pre>
*
* <p>By default, the order in which cells are added to the builder determines
* the iteration ordering of all views in the returned table, with {@link
* #putAll} following the {@link Table#cellSet()} iteration order. However, if
* {@link #orderRowsBy} or {@link #orderColumnsBy} is called, the views are
* sorted by the supplied comparators.
*
* For empty or single-cell immutable tables, {@link #of()} and
* {@link #of(Object, Object, Object)} are even more convenient.
*
* <p>Builder instances can be reused - it is safe to call {@link #build}
* multiple times to build multiple tables in series. Each table is a superset
* of the tables created before it.
*
* @since 11.0
*/
public static final class Builder<R, C, V> {
private final List<Cell<R, C, V>> cells = Lists.newArrayList();
private Comparator<? super R> rowComparator;
private Comparator<? super C> columnComparator;
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableTable#builder}.
*/
public Builder() {}
/**
* Specifies the ordering of the generated table's rows.
*/
public Builder<R, C, V> orderRowsBy(Comparator<? super R> rowComparator) {
this.rowComparator = checkNotNull(rowComparator);
return this;
}
/**
* Specifies the ordering of the generated table's columns.
*/
public Builder<R, C, V> orderColumnsBy(
Comparator<? super C> columnComparator) {
this.columnComparator = checkNotNull(columnComparator);
return this;
}
/**
* Associates the ({@code rowKey}, {@code columnKey}) pair with {@code
* value} in the built table. Duplicate key pairs are not allowed and will
* cause {@link #build} to fail.
*/
public Builder<R, C, V> put(R rowKey, C columnKey, V value) {
cells.add(cellOf(rowKey, columnKey, value));
return this;
}
/**
* Adds the given {@code cell} to the table, making it immutable if
* necessary. Duplicate key pairs are not allowed and will cause {@link
* #build} to fail.
*/
public Builder<R, C, V> put(
Cell<? extends R, ? extends C, ? extends V> cell) {
if (cell instanceof ImmutableCell) {
checkNotNull(cell.getRowKey());
checkNotNull(cell.getColumnKey());
checkNotNull(cell.getValue());
// all supported methods are covariant
Cell<R, C, V> immutableCell = (Cell<R, C, V>) cell;
cells.add(immutableCell);
} else {
put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return this;
}
/**
* Associates all of the given table's keys and values in the built table.
* Duplicate row key column key pairs are not allowed, and will cause
* {@link #build} to fail.
*
* @throws NullPointerException if any key or value in {@code table} is null
*/
public Builder<R, C, V> putAll(
Table<? extends R, ? extends C, ? extends V> table) {
for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
put(cell);
}
return this;
}
/**
* Returns a newly-created immutable table.
*
* @throws IllegalArgumentException if duplicate key pairs were added
*/
public ImmutableTable<R, C, V> build() {
int size = cells.size();
switch (size) {
case 0:
return of();
// case 1:
// return new SingletonImmutableTable<R, C, V>(
// Iterables.getOnlyElement(cells));
default:
return RegularImmutableTable.forCells(
cells, rowComparator, columnComparator);
}
}
}
ImmutableTable() {}
@Override public ImmutableSet<Cell<R, C, V>> cellSet() {
return (ImmutableSet<Cell<R, C, V>>) super.cellSet();
}
@Override
abstract ImmutableSet<Cell<R, C, V>> createCellSet();
@Override
final UnmodifiableIterator<Cell<R, C, V>> cellIterator() {
throw new AssertionError("should never be called");
}
@Override
public ImmutableCollection<V> values() {
return (ImmutableCollection<V>) super.values();
}
@Override
abstract ImmutableCollection<V> createValues();
@Override
final Iterator<V> valuesIterator() {
throw new AssertionError("should never be called");
}
private static <T> T firstNonNull(T first, T second) {
return first != null ? first : checkNotNull(second);
}
/**
* {@inheritDoc}
*
* @throws NullPointerException if {@code columnKey} is {@code null}
*/
@Override public ImmutableMap<R, V> column(C columnKey) {
checkNotNull(columnKey);
return firstNonNull(
(ImmutableMap<R, V>) columnMap().get(columnKey),
ImmutableMap.<R, V>of());
}
@Override public ImmutableSet<C> columnKeySet() {
return columnMap().keySet();
}
/**
* {@inheritDoc}
*
* <p>The value {@code Map<R, V>} instances in the returned map are
* {@link ImmutableMap} instances as well.
*/
@Override public abstract ImmutableMap<C, Map<R, V>> columnMap();
/**
* {@inheritDoc}
*
* @throws NullPointerException if {@code rowKey} is {@code null}
*/
@Override public ImmutableMap<C, V> row(R rowKey) {
checkNotNull(rowKey);
return firstNonNull(
(ImmutableMap<C, V>) rowMap().get(rowKey),
ImmutableMap.<C, V>of());
}
@Override public ImmutableSet<R> rowKeySet() {
return rowMap().keySet();
}
/**
* {@inheritDoc}
*
* <p>The value {@code Map<C, V>} instances in the returned map are
* {@link ImmutableMap} instances as well.
*/
@Override public abstract ImmutableMap<R, Map<C, V>> rowMap();
@Override
public boolean contains(Object rowKey, Object columnKey) {
return get(rowKey, columnKey) != null;
}
@Override
public boolean containsValue(Object value) {
return values().contains(value);
}
/**
* Guaranteed to throw an exception and leave the table unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final void clear() {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the table unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final V put(R rowKey, C columnKey, V value) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the table unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final void putAll(
Table<? extends R, ? extends C, ? extends V> table) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the table unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,49 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
public final class Lists {
public static <E> ArrayList<E> newArrayList() {
return new ArrayList<E>();
}
public static <E> ArrayList<E> newArrayList(E... elements) {
// Avoid integer overflow when a large array is passed in
int capacity = 5 + elements.length + (elements.length / 10);
ArrayList<E> list = new ArrayList<E>(capacity);
Collections.addAll(list, elements);
return list;
}
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
// Let ArrayList's sizing logic work, if possible
return (elements instanceof Collection)
? new ArrayList<E>(Filter.cast(elements))
: newArrayList(elements.iterator());
}
public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
ArrayList<E> list = newArrayList();
Iterators.addAll(list, elements);
return list;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,244 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
import java.lang.reflect.Array;
import java.util.Collection;
/**
* Static utility methods pertaining to object arrays.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
final class ObjectArrays {
static final Object[] EMPTY_ARRAY = new Object[0];
private ObjectArrays() {}
/**
* Returns a new array of the given length with the specified component type.
*
* @param type the component type
* @param length the length of the new array
*/
//
//
// public static <T> T[] newArray(Class<T> type, int length) {
// return (T[]) Array.newInstance(type, length);
// }
/**
* Returns a new array of the given length with the same type as a reference
* array.
*
* @param reference any array of the desired type
* @param length the length of the new array
*/
public static <T> T[] newArray(T[] reference, int length) {
// return Platform.newArray(reference, length);
Class<?> type = reference.getClass().getComponentType();
// the cast is safe because
// result.getClass() == reference.getClass().getComponentType()
T[] result = (T[]) Array.newInstance(type, length);
return result;
}
/**
* Returns a new array that contains the concatenated contents of two arrays.
*
* @param first the first array of elements to concatenate
* @param second the second array of elements to concatenate
* @param type the component type of the returned array
*/
//
// public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
// T[] result = newArray(type, first.length + second.length);
// System.arraycopy(first, 0, result, 0, first.length);
// System.arraycopy(second, 0, result, first.length, second.length);
// return result;
// }
/**
* Returns a new array that prepends {@code element} to {@code array}.
*
* @param element the element to prepend to the front of {@code array}
* @param array the array of elements to append
* @return an array whose size is one larger than {@code array}, with
* {@code element} occupying the first position, and the
* elements of {@code array} occupying the remaining elements.
*/
// public static <T> T[] concat(T element, T[] array) {
// T[] result = newArray(array, array.length + 1);
// result[0] = element;
// System.arraycopy(array, 0, result, 1, array.length);
// return result;
// }
/**
* Returns a new array that appends {@code element} to {@code array}.
*
* @param array the array of elements to prepend
* @param element the element to append to the end
* @return an array whose size is one larger than {@code array}, with
* the same contents as {@code array}, plus {@code element} occupying the
* last position.
*/
// public static <T> T[] concat(T[] array, T element) {
// T[] result = arraysCopyOf(array, array.length + 1);
// result[array.length] = element;
// return result;
// }
/** GWT safe version of Arrays.copyOf. */
static <T> T[] arraysCopyOf(T[] original, int newLength) {
T[] copy = newArray(original, newLength);
System.arraycopy(
original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* Returns an array containing all of the elements in the specified
* collection; the runtime type of the returned array is that of the specified
* array. If the collection fits in the specified array, it is returned
* therein. Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of the specified collection.
*
* <p>If the collection fits in the specified array with room to spare (i.e.,
* the array has more elements than the collection), the element in the array
* immediately following the end of the collection is set to {@code null}.
* This is useful in determining the length of the collection <i>only</i> if
* the caller knows that the collection does not contain any null elements.
*
* <p>This method returns the elements in the order they are returned by the
* collection's iterator.
*
* <p>TODO(kevinb): support concurrently modified collections?
*
* @param c the collection for which to return an array of elements
* @param array the array in which to place the collection elements
* @throws ArrayStoreException if the runtime type of the specified array is
* not a supertype of the runtime type of every element in the specified
* collection
*/
static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
int size = c.size();
if (array.length < size) {
array = newArray(array, size);
}
fillArray(c, array);
if (array.length > size) {
array[size] = null;
}
return array;
}
/**
* Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
* array. the runtime type of the returned array is that of the specified array. If the collection
* fits in the specified array, it is returned therein. Otherwise, a new array is allocated with
* the runtime type of the specified array and the size of the specified collection.
*
* <p>If the collection fits in the specified array with room to spare (i.e., the array has more
* elements than the collection), the element in the array immediately following the end of the
* collection is set to {@code null}. This is useful in determining the length of the collection
* <i>only</i> if the caller knows that the collection does not contain any null elements.
*/
// static <T> T[] toArrayImpl(Object[] src, int offset, int len, T[] dst) {
// checkPositionIndexes(offset, offset + len, src.length);
// if (dst.length < len) {
// dst = newArray(dst, len);
// } else if (dst.length > len) {
// dst[len] = null;
// }
// System.arraycopy(src, offset, dst, 0, len);
// return dst;
// }
/**
* Returns an array containing all of the elements in the specified
* collection. This method returns the elements in the order they are returned
* by the collection's iterator. The returned array is "safe" in that no
* references to it are maintained by the collection. The caller is thus free
* to modify the returned array.
*
* <p>This method assumes that the collection size doesn't change while the
* method is running.
*
* <p>TODO(kevinb): support concurrently modified collections?
*
* @param c the collection for which to return an array of elements
*/
// static Object[] toArrayImpl(Collection<?> c) {
// return fillArray(c, new Object[c.size()]);
// }
/**
* Returns a copy of the specified subrange of the specified array that is literally an Object[],
* and not e.g. a {@code String[]}.
*/
// static Object[] copyAsObjectArray(Object[] elements, int offset, int length) {
// checkPositionIndexes(offset, offset + length, elements.length);
// if (length == 0) {
// return EMPTY_ARRAY;
// }
// Object[] result = new Object[length];
// System.arraycopy(elements, offset, result, 0, length);
// return result;
// }
private static Object[] fillArray(Iterable<?> elements, Object[] array) {
int i = 0;
for (Object element : elements) {
array[i++] = element;
}
return array;
}
/**
* Swaps {@code array[i]} with {@code array[j]}.
*/
// static void swap(Object[] array, int i, int j) {
// Object temp = array[i];
// array[i] = array[j];
// array[j] = temp;
// }
static Object[] checkElementsNotNull(Object... array) {
return checkElementsNotNull(array, array.length);
}
static Object[] checkElementsNotNull(Object[] array, int length) {
for (int i = 0; i < length; i++) {
checkElementNotNull(array[i], i);
}
return array;
}
// We do this instead of Preconditions.checkNotNull to save boxing and array
// creation cost.
static Object checkElementNotNull(Object element, int index) {
if (element == null) {
throw new NullPointerException("at index " + index);
}
return element;
}
}

View file

@ -1,350 +0,0 @@
package game.collect;
final class Preconditions {
private Preconditions() {}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @throws IllegalArgumentException if {@code expression} is false
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
public static void checkArgument(boolean expression,
String errorMessageTemplate,
Object... errorMessageArgs) {
if (!expression) {
throw new IllegalArgumentException(String.format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalStateException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @throws IllegalStateException if {@code expression} is false
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
// public static void checkState(boolean expression,
// String errorMessageTemplate,
// Object... errorMessageArgs) {
// if (!expression) {
// throw new IllegalStateException(String.format(errorMessageTemplate, errorMessageArgs));
// }
// }
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference, Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
// public static <T> T checkNotNull(T reference,
// String errorMessageTemplate,
// Object... errorMessageArgs) {
// if (reference == null) {
// // If either of these parameters is null, the right thing happens anyway
// throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
// }
// return reference;
// }
/*
* All recent hotspots (as of 2009) *really* like to have the natural code
*
* if (guardExpression) {
* throw new BadException(messageExpression);
* }
*
* refactored so that messageExpression is moved to a separate String-returning method.
*
* if (guardExpression) {
* throw new BadException(badMsg(...));
* }
*
* The alternative natural refactorings into void or Exception-returning methods are much slower.
* This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This
* is a hotspot optimizer bug, which should be fixed, but that's a separate, big project).
*
* The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a
* RangeCheckMicroBenchmark in the JDK that was used to test this.
*
* But the methods in this class want to throw different exceptions, depending on the args, so it
* appears that this pattern is not directly applicable. But we can use the ridiculous, devious
* trick of throwing an exception in the middle of the construction of another exception. Hotspot
* is fine with that.
*/
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
* {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
// public static int checkElementIndex(int index, int size) {
// return checkElementIndex(index, size, "index");
// }
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
* {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkElementIndex(
int index, int size) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(badElementIndex(index, size));
}
return index;
}
private static String badElementIndex(int index, int size) {
if (index < 0) {
return String.format("index (%d) must not be negative", index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index >= size
return String.format("index (%d) must be less than size (%d)", index, size);
}
}
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
* size {@code size}. A position index may range from zero to {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
// public static int checkPositionIndex(int index, int size) {
// return checkPositionIndex(index, size, "index");
// }
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
* size {@code size}. A position index may range from zero to {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkPositionIndex(int index, int size) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException(badPositionIndex(index, size, "index"));
}
return index;
}
private static String badPositionIndex(int index, int size, String desc) {
if (index < 0) {
return String.format("%s (%d) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index > size
return String.format("%s (%d) must not be greater than size (%s)", desc, index, size);
}
}
/**
* Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
* or string of size {@code size}, and are in order. A position index may range from zero to
* {@code size}, inclusive.
*
* @param start a user-supplied index identifying a starting position in an array, list or string
* @param end a user-supplied index identifying a ending position in an array, list or string
* @param size the size of that array, list or string
* @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size},
* or if {@code end} is less than {@code start}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static void checkPositionIndexes(int start, int end, int size) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (start < 0 || end < start || end > size) {
throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
}
}
private static String badPositionIndexes(int start, int end, int size) {
if (start < 0 || start > size) {
return badPositionIndex(start, size, "start index");
}
if (end < 0 || end > size) {
return badPositionIndex(end, size, "end index");
}
// end < start
return String.format("end index (%d) must not be less than start index (%d)", end, start);
}
public static boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Substitutes each {@code %s} in {@code template} with an argument. These are matched by
* position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than
* placeholders, the unmatched arguments will be appended to the end of the formatted message in
* square braces.
*
* @param template a non-null string containing 0 or more {@code %s} placeholders.
* @param args the arguments to be substituted into the message template. Arguments are converted
* to strings using {@link String#valueOf(Object)}. Arguments can be null.
*/
// // Note that this is somewhat-improperly used from Verify.java as well.
// static String format(String template, Object... args) {
// template = String.valueOf(template); // null -> "null"
//
// // start substituting the arguments into the '%s' placeholders
// StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
// int templateStart = 0;
// int i = 0;
// while (i < args.length) {
// int placeholderStart = template.indexOf("%s", templateStart);
// if (placeholderStart == -1) {
// break;
// }
// builder.append(template.substring(templateStart, placeholderStart));
// builder.append(args[i++]);
// templateStart = placeholderStart + 2;
// }
// builder.append(template.substring(templateStart));
//
// // if we run out of placeholders, append the extra args in square braces
// if (i < args.length) {
// builder.append(" [");
// builder.append(args[i++]);
// while (i < args.length) {
// builder.append(", ");
// builder.append(args[i++]);
// }
// builder.append(']');
// }
//
// return builder.toString();
// }
}

View file

@ -1,65 +0,0 @@
/*
* Copyright (C) 2012 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 game.collect;
/**
* An {@link ImmutableAsList} implementation specialized for when the delegate collection is
* already backed by an {@code ImmutableList} or array.
*
* @author Louis Wasserman
*/
// uses writeReplace, not default serialization
class RegularImmutableAsList<E> extends ImmutableAsList<E> {
private final ImmutableCollection<E> delegate;
private final ImmutableList<? extends E> delegateList;
RegularImmutableAsList(ImmutableCollection<E> delegate, ImmutableList<? extends E> delegateList) {
this.delegate = delegate;
this.delegateList = delegateList;
}
RegularImmutableAsList(ImmutableCollection<E> delegate, Object[] array) {
this(delegate, ImmutableList.<E>asImmutableList(array));
}
@Override
ImmutableCollection<E> delegateCollection() {
return delegate;
}
ImmutableList<? extends E> delegateList() {
return delegateList;
}
// safe covariant cast!
@Override
public UnmodifiableListIterator<E> listIterator(int index) {
return (UnmodifiableListIterator<E>) delegateList.listIterator(index);
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return delegateList.copyIntoArray(dst, offset);
}
@Override
public E get(int index) {
return delegateList.get(index);
}
}

View file

@ -1,106 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
/**
* Implementation of {@link ImmutableList} with one or more elements.
*
* @author Kevin Bourrillion
*/
// uses writeReplace(), not default serialization
class RegularImmutableList<E> extends ImmutableList<E> {
private final transient int offset;
private final transient int size;
private final transient Object[] array;
RegularImmutableList(Object[] array, int offset, int size) {
this.offset = offset;
this.size = size;
this.array = array;
}
RegularImmutableList(Object[] array) {
this(array, 0, array.length);
}
@Override
public int size() {
return size;
}
@Override boolean isPartialView() {
return size != array.length;
}
@Override
int copyIntoArray(Object[] dst, int dstOff) {
System.arraycopy(array, offset, dst, dstOff, size);
return dstOff + size;
}
// The fake cast to E is safe because the creation methods only allow E's
@Override
public E get(int index) {
Preconditions.checkElementIndex(index, size);
return (E) array[index + offset];
}
@Override
public int indexOf(Object object) {
if (object == null) {
return -1;
}
for (int i = 0; i < size; i++) {
if (array[offset + i].equals(object)) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(Object object) {
if (object == null) {
return -1;
}
for (int i = size - 1; i >= 0; i--) {
if (array[offset + i].equals(object)) {
return i;
}
}
return -1;
}
@Override
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
return new RegularImmutableList<E>(
array, offset + fromIndex, toIndex - fromIndex);
}
@Override
public UnmodifiableListIterator<E> listIterator(int index) {
// for performance
// The fake cast to E is safe because the creation methods only allow E's
return (UnmodifiableListIterator<E>)
Iterators.forArray(array, offset, size, index);
}
// TODO(user): benchmark optimizations for equals() and see if they're worthwhile
}

View file

@ -1,205 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.CollectPreconditions.checkEntryNotNull;
import game.collect.ImmutableMapEntry.TerminalEntry;
/**
* Implementation of {@link ImmutableMap} with two or more entries.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
* @author Gregory Kick
*/
final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
// entries in insertion order
private final transient ImmutableMapEntry<K, V>[] entries;
// array of linked lists of entries
private final transient ImmutableMapEntry<K, V>[] table;
// 'and' with an int to get a table index
private final transient int mask;
RegularImmutableMap(TerminalEntry<?, ?>... theEntries) {
this(theEntries.length, theEntries);
}
/**
* Constructor for RegularImmutableMap that takes as input an array of {@code TerminalEntry}
* entries. Assumes that these entries have already been checked for null.
*
* <p>This allows reuse of the entry objects from the array in the actual implementation.
*/
RegularImmutableMap(int size, TerminalEntry<?, ?>[] theEntries) {
entries = createEntryArray(size);
int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
table = createEntryArray(tableSize);
mask = tableSize - 1;
for (int entryIndex = 0; entryIndex < size; entryIndex++) {
TerminalEntry<K, V> entry = (TerminalEntry<K, V>) theEntries[entryIndex];
K key = entry.getKey();
int tableIndex = Hashing.smear(key.hashCode()) & mask;
ImmutableMapEntry<K, V> existing = table[tableIndex];
// prepend, not append, so the entries can be immutable
ImmutableMapEntry<K, V> newEntry = (existing == null)
? entry
: new NonTerminalMapEntry<K, V>(entry, existing);
table[tableIndex] = newEntry;
entries[entryIndex] = newEntry;
checkNoConflictInBucket(key, newEntry, existing);
}
}
/**
* Constructor for RegularImmutableMap that makes no assumptions about the input entries.
*/
RegularImmutableMap(Entry<?, ?>[] theEntries) {
int size = theEntries.length;
entries = createEntryArray(size);
int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
table = createEntryArray(tableSize);
mask = tableSize - 1;
for (int entryIndex = 0; entryIndex < size; entryIndex++) {
// all our callers carefully put in only Entry<K, V>s
Entry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];
K key = entry.getKey();
V value = entry.getValue();
checkEntryNotNull(key, value);
int tableIndex = Hashing.smear(key.hashCode()) & mask;
ImmutableMapEntry<K, V> existing = table[tableIndex];
// prepend, not append, so the entries can be immutable
ImmutableMapEntry<K, V> newEntry = (existing == null)
? new TerminalEntry<K, V>(key, value)
: new NonTerminalMapEntry<K, V>(key, value, existing);
table[tableIndex] = newEntry;
entries[entryIndex] = newEntry;
checkNoConflictInBucket(key, newEntry, existing);
}
}
private void checkNoConflictInBucket(
K key, ImmutableMapEntry<K, V> entry, ImmutableMapEntry<K, V> bucketHead) {
for (; bucketHead != null; bucketHead = bucketHead.getNextInKeyBucket()) {
checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead);
}
}
private static final class NonTerminalMapEntry<K, V> extends ImmutableMapEntry<K, V> {
private final ImmutableMapEntry<K, V> nextInKeyBucket;
NonTerminalMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {
super(key, value);
this.nextInKeyBucket = nextInKeyBucket;
}
NonTerminalMapEntry(ImmutableMapEntry<K, V> contents, ImmutableMapEntry<K, V> nextInKeyBucket) {
super(contents);
this.nextInKeyBucket = nextInKeyBucket;
}
@Override
ImmutableMapEntry<K, V> getNextInKeyBucket() {
return nextInKeyBucket;
}
@Override
ImmutableMapEntry<K, V> getNextInValueBucket() {
return null;
}
}
/**
* Closed addressing tends to perform well even with high load factors.
* Being conservative here ensures that the table is still likely to be
* relatively sparse (hence it misses fast) while saving space.
*/
private static final double MAX_LOAD_FACTOR = 1.2;
/**
* Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The
* result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or
* allowed to escape the class.
*/
// Safe as long as the javadocs are followed
private ImmutableMapEntry<K, V>[] createEntryArray(int size) {
return new ImmutableMapEntry[size];
}
@Override public V get(Object key) {
if (key == null) {
return null;
}
int index = Hashing.smear(key.hashCode()) & mask;
for (ImmutableMapEntry<K, V> entry = table[index];
entry != null;
entry = entry.getNextInKeyBucket()) {
K candidateKey = entry.getKey();
/*
* Assume that equals uses the == optimization when appropriate, and that
* it would check hash codes as an optimization when appropriate. If we
* did these things, it would just make things worse for the most
* performance-conscious users.
*/
if (key.equals(candidateKey)) {
return entry.getValue();
}
}
return null;
}
@Override
public int size() {
return entries.length;
}
@Override boolean isPartialView() {
return false;
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
return new EntrySet();
}
// uses writeReplace(), not default serialization
private class EntrySet extends ImmutableMapEntrySet<K, V> {
@Override ImmutableMap<K, V> map() {
return RegularImmutableMap.this;
}
@Override
public UnmodifiableIterator<Entry<K, V>> iterator() {
return asList().iterator();
}
@Override
ImmutableList<Entry<K, V>> createAsList() {
return new RegularImmutableAsList<Entry<K, V>>(this, entries);
}
}
// This class is never actually serialized directly, but we have to make the
// warning go away (and suppressing would suppress for all nested classes too)
private static final long serialVersionUID = 0;
}

View file

@ -1,92 +0,0 @@
/*
* Copyright (C) 2007 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 game.collect;
/**
* Implementation of {@link ImmutableSet} with two or more elements.
*
* @author Kevin Bourrillion
*/
// uses writeReplace(), not default serialization
final class RegularImmutableSet<E> extends ImmutableSet<E> {
private final Object[] elements;
// the same elements in hashed positions (plus nulls)
// @VisibleForTesting
final transient Object[] table;
// 'and' with an int to get a valid table index.
private final transient int mask;
private final transient int hashCode;
RegularImmutableSet(
Object[] elements, int hashCode, Object[] table, int mask) {
this.elements = elements;
this.table = table;
this.mask = mask;
this.hashCode = hashCode;
}
@Override public boolean contains(Object target) {
if (target == null) {
return false;
}
for (int i = Hashing.smear(target.hashCode()); true; i++) {
Object candidate = table[i & mask];
if (candidate == null) {
return false;
}
if (candidate.equals(target)) {
return true;
}
}
}
@Override
public int size() {
return elements.length;
}
// all elements are E's
@Override
public UnmodifiableIterator<E> iterator() {
return (UnmodifiableIterator<E>) Iterators.forArray(elements);
}
@Override
int copyIntoArray(Object[] dst, int offset) {
System.arraycopy(elements, 0, dst, offset, elements.length);
return offset + elements.length;
}
@Override
ImmutableList<E> createAsList() {
return new RegularImmutableAsList<E>(this, elements);
}
@Override
boolean isPartialView() {
return false;
}
@Override public int hashCode() {
return hashCode;
}
@Override boolean isHashCodeFast() {
return true;
}
}

View file

@ -1,175 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import static game.collect.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* An implementation of {@link ImmutableTable} holding an arbitrary number of
* cells.
*
* @author Gregory Kick
*/
abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
RegularImmutableTable() {}
abstract Cell<R, C, V> getCell(int iterationIndex);
@Override
final ImmutableSet<Cell<R, C, V>> createCellSet() {
return isEmpty() ? ImmutableSet.<Cell<R, C, V>>of() : new CellSet();
}
private final class CellSet extends ImmutableSet<Cell<R, C, V>> {
@Override
public int size() {
return RegularImmutableTable.this.size();
}
@Override
public UnmodifiableIterator<Cell<R, C, V>> iterator() {
return asList().iterator();
}
@Override
ImmutableList<Cell<R, C, V>> createAsList() {
return new ImmutableAsList<Cell<R, C, V>>() {
@Override
public Cell<R, C, V> get(int index) {
return getCell(index);
}
@Override
ImmutableCollection<Cell<R, C, V>> delegateCollection() {
return CellSet.this;
}
};
}
@Override
public boolean contains(Object object) {
if (object instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) object;
Object value = get(cell.getRowKey(), cell.getColumnKey());
return value != null && value.equals(cell.getValue());
}
return false;
}
@Override
boolean isPartialView() {
return false;
}
}
abstract V getValue(int iterationIndex);
@Override
final ImmutableCollection<V> createValues() {
return isEmpty() ? ImmutableList.<V>of() : new Values();
}
private final class Values extends ImmutableList<V> {
@Override
public int size() {
return RegularImmutableTable.this.size();
}
@Override
public V get(int index) {
return getValue(index);
}
@Override
boolean isPartialView() {
return true;
}
}
static <R, C, V> RegularImmutableTable<R, C, V> forCells(
List<Cell<R, C, V>> cells,
final Comparator<? super R> rowComparator,
final Comparator<? super C> columnComparator) {
checkNotNull(cells);
if (rowComparator != null || columnComparator != null) {
/*
* This sorting logic leads to a cellSet() ordering that may not be expected and that isn't
* documented in the Javadoc. If a row Comparator is provided, cellSet() iterates across the
* columns in the first row, the columns in the second row, etc. If a column Comparator is
* provided but a row Comparator isn't, cellSet() iterates across the rows in the first
* column, the rows in the second column, etc.
*/
Comparator<Cell<R, C, V>> comparator = new Comparator<Cell<R, C, V>>() {
@Override public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
int rowCompare = (rowComparator == null) ? 0
: rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
if (rowCompare != 0) {
return rowCompare;
}
return (columnComparator == null) ? 0
: columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
}
};
Collections.sort(cells, comparator);
}
return forCellsInternal(cells, rowComparator, columnComparator);
}
static <R, C, V> RegularImmutableTable<R, C, V> forCells(
Iterable<Cell<R, C, V>> cells) {
return forCellsInternal(cells, null, null);
}
/**
* A factory that chooses the most space-efficient representation of the
* table.
*/
private static final <R, C, V> RegularImmutableTable<R, C, V>
forCellsInternal(Iterable<Cell<R, C, V>> cells,
Comparator<? super R> rowComparator,
Comparator<? super C> columnComparator) {
ImmutableSet.Builder<R> rowSpaceBuilder = ImmutableSet.builder();
ImmutableSet.Builder<C> columnSpaceBuilder = ImmutableSet.builder();
ImmutableList<Cell<R, C, V>> cellList = ImmutableList.copyOf(cells);
for (Cell<R, C, V> cell : cellList) {
rowSpaceBuilder.add(cell.getRowKey());
columnSpaceBuilder.add(cell.getColumnKey());
}
ImmutableSet<R> rowSpace = rowSpaceBuilder.build();
if (rowComparator != null) {
List<R> rowList = Lists.newArrayList(rowSpace);
Collections.sort(rowList, rowComparator);
rowSpace = ImmutableSet.copyOf(rowList);
}
ImmutableSet<C> columnSpace = columnSpaceBuilder.build();
if (columnComparator != null) {
List<C> columnList = Lists.newArrayList(columnSpace);
Collections.sort(columnList, columnComparator);
columnSpace = ImmutableSet.copyOf(columnList);
}
// use a dense table if more than half of the cells have values
// TODO(gak): tune this condition based on empirical evidence
return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2)) ?
new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace) :
new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,108 +0,0 @@
/*
* Copyright (C) 2009 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 game.collect;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A {@code RegularImmutableTable} optimized for sparse data.
*/
//@Immutable
final class SparseImmutableTable<R, C, V>
extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Map<C, V>> rowMap;
private final ImmutableMap<C, Map<R, V>> columnMap;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
SparseImmutableTable(ImmutableList<Cell<R, C, V>> cellList,
ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
Map<R, Integer> rowIndex = Maps.newHashMap();
Map<R, Map<C, V>> rows = Maps.newLinkedHashMap();
for (R row : rowSpace) {
rowIndex.put(row, rows.size());
rows.put(row, new LinkedHashMap<C, V>());
}
Map<C, Map<R, V>> columns = Maps.newLinkedHashMap();
for (C col : columnSpace) {
columns.put(col, new LinkedHashMap<R, V>());
}
int[] iterationOrderRow = new int[cellList.size()];
int[] iterationOrderColumn = new int[cellList.size()];
for (int i = 0; i < cellList.size(); i++) {
Cell<R, C, V> cell = cellList.get(i);
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
V value = cell.getValue();
iterationOrderRow[i] = rowIndex.get(rowKey);
Map<C, V> thisRow = rows.get(rowKey);
iterationOrderColumn[i] = thisRow.size();
V oldValue = thisRow.put(columnKey, value);
if (oldValue != null) {
throw new IllegalArgumentException("Duplicate value for row=" + rowKey + ", column="
+ columnKey + ": " + value + ", " + oldValue);
}
columns.get(columnKey).put(rowKey, value);
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
ImmutableMap.Builder<R, Map<C, V>> rowBuilder = ImmutableMap.builder();
for (Map.Entry<R, Map<C, V>> row : rows.entrySet()) {
rowBuilder.put(row.getKey(), ImmutableMap.copyOf(row.getValue()));
}
this.rowMap = rowBuilder.build();
ImmutableMap.Builder<C, Map<R, V>> columnBuilder = ImmutableMap.builder();
for (Map.Entry<C, Map<R, V>> col : columns.entrySet()) {
columnBuilder.put(col.getKey(), ImmutableMap.copyOf(col.getValue()));
}
this.columnMap = columnBuilder.build();
}
@Override public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
@Override public ImmutableMap<R, Map<C, V>> rowMap() {
return rowMap;
}
@Override
public int size() {
return iterationOrderRow.length;
}
@Override
Cell<R, C, V> getCell(int index) {
int rowIndex = iterationOrderRow[index];
Map.Entry<R, Map<C, V>> rowEntry = rowMap.entrySet().asList().get(rowIndex);
ImmutableMap<C, V> row = (ImmutableMap<C, V>) rowEntry.getValue();
int columnIndex = iterationOrderColumn[index];
Map.Entry<C, V> colEntry = row.entrySet().asList().get(columnIndex);
return cellOf(rowEntry.getKey(), colEntry.getKey(), colEntry.getValue());
}
@Override
V getValue(int index) {
int rowIndex = iterationOrderRow[index];
ImmutableMap<C, V> row = (ImmutableMap<C, V>) rowMap.values().asList().get(rowIndex);
int columnIndex = iterationOrderColumn[index];
return row.values().asList().get(columnIndex);
}
}

View file

@ -1,891 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import static game.collect.Maps.safeContainsKey;
import static game.collect.Maps.safeGet;
import static game.collect.Preconditions.checkNotNull;
import static game.util.Predicates.alwaysTrue;
import static game.util.Predicates.equalTo;
import static game.util.Predicates.in;
import static game.util.Predicates.not;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import game.collect.Maps.ImprovedAbstractMap;
import game.collect.Sets.ImprovedAbstractSet;
/**
* {@link Table} implementation backed by a map that associates row keys with
* column key / value secondary maps. This class provides rapid access to
* records by the row key alone or by both keys, but not by just the column key.
*
* <p>The views returned by {@link #column}, {@link #columnKeySet()}, and {@link
* #columnMap()} have iterators that don't support {@code remove()}. Otherwise,
* all optional operations are supported. Null row keys, columns keys, and
* values are not supported.
*
* <p>Lookups by row key are often faster than lookups by column key, because
* the data is stored in a {@code Map<R, Map<C, V>>}. A method call like {@code
* column(columnKey).get(rowKey)} still runs quickly, since the row key is
* provided. However, {@code column(columnKey).size()} takes longer, since an
* iteration across all row keys occurs.
*
* <p>Note that this implementation is not synchronized. If multiple threads
* access this table concurrently and one of the threads modifies the table, it
* must be synchronized externally.
*
* @author Jared Levy
*/
public class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializable {
final Map<R, Map<C, V>> backingMap = new HashMap<R, Map<C, V>>();
// final Supplier<? extends Map<C, V>> factory;
// StandardTable(Map<R, Map<C, V>> backingMap) {
// this.backingMap = backingMap;
//// this.factory = factory;
// }
// Accessors
@Override public boolean contains(
Object rowKey, Object columnKey) {
return rowKey != null && columnKey != null && super.contains(rowKey, columnKey);
}
@Override public boolean containsColumn(Object columnKey) {
if (columnKey == null) {
return false;
}
for (Map<C, V> map : backingMap.values()) {
if (safeContainsKey(map, columnKey)) {
return true;
}
}
return false;
}
@Override public boolean containsRow(Object rowKey) {
return rowKey != null && safeContainsKey(backingMap, rowKey);
}
@Override public boolean containsValue(Object value) {
return value != null && super.containsValue(value);
}
@Override public V get(Object rowKey, Object columnKey) {
return (rowKey == null || columnKey == null)
? null
: super.get(rowKey, columnKey);
}
@Override public boolean isEmpty() {
return backingMap.isEmpty();
}
@Override public int size() {
int size = 0;
for (Map<C, V> map : backingMap.values()) {
size += map.size();
}
return size;
}
// Mutators
@Override public void clear() {
backingMap.clear();
}
private Map<C, V> getOrCreate(R rowKey) {
Map<C, V> map = backingMap.get(rowKey);
if (map == null) {
map = Maps.newHashMapWithExpectedSize(0);
// map = factory.get();
backingMap.put(rowKey, map);
}
return map;
}
@Override public V put(R rowKey, C columnKey, V value) {
checkNotNull(rowKey);
checkNotNull(columnKey);
checkNotNull(value);
return getOrCreate(rowKey).put(columnKey, value);
}
@Override public V remove(
Object rowKey, Object columnKey) {
if ((rowKey == null) || (columnKey == null)) {
return null;
}
Map<C, V> map = safeGet(backingMap, rowKey);
if (map == null) {
return null;
}
V value = map.remove(columnKey);
if (map.isEmpty()) {
backingMap.remove(rowKey);
}
return value;
}
private Map<R, V> removeColumn(Object column) {
Map<R, V> output = new LinkedHashMap<R, V>();
Iterator<Entry<R, Map<C, V>>> iterator
= backingMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<R, Map<C, V>> entry = iterator.next();
V value = entry.getValue().remove(column);
if (value != null) {
output.put(entry.getKey(), value);
if (entry.getValue().isEmpty()) {
iterator.remove();
}
}
}
return output;
}
private boolean containsMapping(
Object rowKey, Object columnKey, Object value) {
return value != null && value.equals(get(rowKey, columnKey));
}
/** Remove a row key / column key / value mapping, if present. */
private boolean removeMapping(Object rowKey, Object columnKey, Object value) {
if (containsMapping(rowKey, columnKey, value)) {
remove(rowKey, columnKey);
return true;
}
return false;
}
// Views
/**
* Abstract set whose {@code isEmpty()} returns whether the table is empty and
* whose {@code clear()} clears all table mappings.
*/
private abstract class TableSet<T> extends ImprovedAbstractSet<T> {
@Override public boolean isEmpty() {
return backingMap.isEmpty();
}
@Override public void clear() {
backingMap.clear();
}
}
/**
* {@inheritDoc}
*
* <p>The set's iterator traverses the mappings for the first row, the
* mappings for the second row, and so on.
*
* <p>Each cell is an immutable snapshot of a row key / column key / value
* mapping, taken at the time the cell is returned by a method call to the
* set or its iterator.
*/
@Override public Set<Cell<R, C, V>> cellSet() {
return super.cellSet();
}
@Override Iterator<Cell<R, C, V>> cellIterator() {
return new CellIterator();
}
private class CellIterator implements Iterator<Cell<R, C, V>> {
final Iterator<Entry<R, Map<C, V>>> rowIterator
= backingMap.entrySet().iterator();
Entry<R, Map<C, V>> rowEntry;
Iterator<Entry<C, V>> columnIterator
= Iterators.emptyModifiableIterator();
@Override public boolean hasNext() {
return rowIterator.hasNext() || columnIterator.hasNext();
}
@Override public Cell<R, C, V> next() {
if (!columnIterator.hasNext()) {
rowEntry = rowIterator.next();
columnIterator = rowEntry.getValue().entrySet().iterator();
}
Entry<C, V> columnEntry = columnIterator.next();
return ImmutableTable.immutableCell(
rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
}
@Override public void remove() {
columnIterator.remove();
if (rowEntry.getValue().isEmpty()) {
rowIterator.remove();
}
}
}
@Override public Map<C, V> row(R rowKey) {
return new Row(rowKey);
}
class Row extends ImprovedAbstractMap<C, V> {
final R rowKey;
Row(R rowKey) {
this.rowKey = checkNotNull(rowKey);
}
Map<C, V> backingRowMap;
Map<C, V> backingRowMap() {
return (backingRowMap == null
|| (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
? backingRowMap = computeBackingRowMap()
: backingRowMap;
}
Map<C, V> computeBackingRowMap() {
return backingMap.get(rowKey);
}
// Call this every time we perform a removal.
void maintainEmptyInvariant() {
if (backingRowMap() != null && backingRowMap.isEmpty()) {
backingMap.remove(rowKey);
backingRowMap = null;
}
}
@Override
public boolean containsKey(Object key) {
Map<C, V> backingRowMap = backingRowMap();
return (key != null && backingRowMap != null)
&& Maps.safeContainsKey(backingRowMap, key);
}
@Override
public V get(Object key) {
Map<C, V> backingRowMap = backingRowMap();
return (key != null && backingRowMap != null)
? Maps.safeGet(backingRowMap, key)
: null;
}
@Override
public V put(C key, V value) {
checkNotNull(key);
checkNotNull(value);
if (backingRowMap != null && !backingRowMap.isEmpty()) {
return backingRowMap.put(key, value);
}
return StandardTable.this.put(rowKey, key, value);
}
@Override
public V remove(Object key) {
Map<C, V> backingRowMap = backingRowMap();
if (backingRowMap == null) {
return null;
}
V result = Maps.safeRemove(backingRowMap, key);
maintainEmptyInvariant();
return result;
}
@Override
public void clear() {
Map<C, V> backingRowMap = backingRowMap();
if (backingRowMap != null) {
backingRowMap.clear();
}
maintainEmptyInvariant();
}
@Override
protected Set<Entry<C, V>> createEntrySet() {
return new RowEntrySet();
}
private final class RowEntrySet extends Maps.EntrySet<C, V> {
@Override
Map<C, V> map() {
return Row.this;
}
@Override
public int size() {
Map<C, V> map = backingRowMap();
return (map == null) ? 0 : map.size();
}
@Override
public Iterator<Entry<C, V>> iterator() {
final Map<C, V> map = backingRowMap();
if (map == null) {
return Iterators.emptyModifiableIterator();
}
final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
return new Iterator<Entry<C, V>>() {
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public Entry<C, V> next() {
final Entry<C, V> entry = iterator.next();
return new ForwardingMapEntry<C, V>() {
@Override protected Entry<C, V> delegate() {
return entry;
}
@Override public V setValue(V value) {
return super.setValue(checkNotNull(value));
}
@Override
public boolean equals(Object object) {
// TODO(user): identify why this affects GWT tests
return standardEquals(object);
}
};
}
@Override
public void remove() {
iterator.remove();
maintainEmptyInvariant();
}
};
}
}
}
/**
* {@inheritDoc}
*
* <p>The returned map's views have iterators that don't support
* {@code remove()}.
*/
@Override public Map<R, V> column(C columnKey) {
return new Column(columnKey);
}
private class Column extends ImprovedAbstractMap<R, V> {
final C columnKey;
Column(C columnKey) {
this.columnKey = checkNotNull(columnKey);
}
@Override public V put(R key, V value) {
return StandardTable.this.put(key, columnKey, value);
}
@Override public V get(Object key) {
return StandardTable.this.get(key, columnKey);
}
@Override public boolean containsKey(Object key) {
return StandardTable.this.contains(key, columnKey);
}
@Override public V remove(Object key) {
return StandardTable.this.remove(key, columnKey);
}
/**
* Removes all {@code Column} mappings whose row key and value satisfy the
* given predicate.
*/
boolean removeFromColumnIf(Predicate<? super Entry<R, V>> predicate) {
boolean changed = false;
Iterator<Entry<R, Map<C, V>>> iterator
= backingMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<R, Map<C, V>> entry = iterator.next();
Map<C, V> map = entry.getValue();
V value = map.get(columnKey);
if (value != null
&& predicate.test(Maps.immutableEntry(entry.getKey(), value))) {
map.remove(columnKey);
changed = true;
if (map.isEmpty()) {
iterator.remove();
}
}
}
return changed;
}
@Override Set<Entry<R, V>> createEntrySet() {
return new EntrySet();
}
private class EntrySet extends ImprovedAbstractSet<Entry<R, V>> {
@Override public Iterator<Entry<R, V>> iterator() {
return new EntrySetIterator();
}
@Override public int size() {
int size = 0;
for (Map<C, V> map : backingMap.values()) {
if (map.containsKey(columnKey)) {
size++;
}
}
return size;
}
@Override public boolean isEmpty() {
return !containsColumn(columnKey);
}
@Override public void clear() {
removeFromColumnIf(alwaysTrue());
}
@Override public boolean contains(Object o) {
if (o instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) o;
return containsMapping(entry.getKey(), columnKey, entry.getValue());
}
return false;
}
@Override public boolean remove(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return removeMapping(entry.getKey(), columnKey, entry.getValue());
}
return false;
}
@Override public boolean retainAll(Collection<?> c) {
return removeFromColumnIf(not(in(c)));
}
}
private class EntrySetIterator extends AbstractIterator<Entry<R, V>> {
final Iterator<Entry<R, Map<C, V>>> iterator
= backingMap.entrySet().iterator();
@Override protected Entry<R, V> computeNext() {
while (iterator.hasNext()) {
final Entry<R, Map<C, V>> entry = iterator.next();
if (entry.getValue().containsKey(columnKey)) {
return new AbstractMapEntry<R, V>() {
@Override public R getKey() {
return entry.getKey();
}
@Override public V getValue() {
return entry.getValue().get(columnKey);
}
@Override public V setValue(V value) {
return entry.getValue().put(columnKey, checkNotNull(value));
}
};
}
}
return endOfData();
}
}
@Override Set<R> createKeySet() {
return new KeySet();
}
private class KeySet extends Maps.KeySet<R, V> {
KeySet() {
super(Column.this);
}
@Override public boolean contains(Object obj) {
return StandardTable.this.contains(obj, columnKey);
}
@Override public boolean remove(Object obj) {
return StandardTable.this.remove(obj, columnKey) != null;
}
@Override public boolean retainAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<R>keyPredicateOnEntries(not(in(c))));
}
}
@Override
Collection<V> createValues() {
return new Values();
}
private class Values extends Maps.Values<R, V> {
Values() {
super(Column.this);
}
@Override public boolean remove(Object obj) {
return obj != null && removeFromColumnIf(Maps.<V>valuePredicateOnEntries(equalTo(obj)));
}
@Override public boolean removeAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(in(c)));
}
@Override public boolean retainAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(not(in(c))));
}
}
}
@Override public Set<R> rowKeySet() {
return rowMap().keySet();
}
private transient Set<C> columnKeySet;
/**
* {@inheritDoc}
*
* <p>The returned set has an iterator that does not support {@code remove()}.
*
* <p>The set's iterator traverses the columns of the first row, the
* columns of the second row, etc., skipping any columns that have
* appeared previously.
*/
@Override
public Set<C> columnKeySet() {
Set<C> result = columnKeySet;
return (result == null) ? columnKeySet = new ColumnKeySet() : result;
}
private class ColumnKeySet extends TableSet<C> {
@Override public Iterator<C> iterator() {
return createColumnKeyIterator();
}
@Override public int size() {
return Iterators.size(iterator());
}
@Override public boolean remove(Object obj) {
if (obj == null) {
return false;
}
boolean changed = false;
Iterator<Map<C, V>> iterator = backingMap.values().iterator();
while (iterator.hasNext()) {
Map<C, V> map = iterator.next();
if (map.keySet().remove(obj)) {
changed = true;
if (map.isEmpty()) {
iterator.remove();
}
}
}
return changed;
}
@Override public boolean removeAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
Iterator<Map<C, V>> iterator = backingMap.values().iterator();
while (iterator.hasNext()) {
Map<C, V> map = iterator.next();
// map.keySet().removeAll(c) can throw a NPE when map is a TreeMap with
// natural ordering and c contains a null.
if (Iterators.removeAll(map.keySet().iterator(), c)) {
changed = true;
if (map.isEmpty()) {
iterator.remove();
}
}
}
return changed;
}
@Override public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
Iterator<Map<C, V>> iterator = backingMap.values().iterator();
while (iterator.hasNext()) {
Map<C, V> map = iterator.next();
if (map.keySet().retainAll(c)) {
changed = true;
if (map.isEmpty()) {
iterator.remove();
}
}
}
return changed;
}
@Override public boolean contains(Object obj) {
return containsColumn(obj);
}
}
/**
* Creates an iterator that returns each column value with duplicates
* omitted.
*/
Iterator<C> createColumnKeyIterator() {
return new ColumnKeyIterator();
}
private class ColumnKeyIterator extends AbstractIterator<C> {
// Use the same map type to support TreeMaps with comparators that aren't
// consistent with equals().
final Map<C, V> seen = Maps.newHashMapWithExpectedSize(0);
final Iterator<Map<C, V>> mapIterator = backingMap.values().iterator();
Iterator<Entry<C, V>> entryIterator = Iterators.emptyIterator();
@Override protected C computeNext() {
while (true) {
if (entryIterator.hasNext()) {
Entry<C, V> entry = entryIterator.next();
if (!seen.containsKey(entry.getKey())) {
seen.put(entry.getKey(), entry.getValue());
return entry.getKey();
}
} else if (mapIterator.hasNext()) {
entryIterator = mapIterator.next().entrySet().iterator();
} else {
return endOfData();
}
}
}
}
/**
* {@inheritDoc}
*
* <p>The collection's iterator traverses the values for the first row,
* the values for the second row, and so on.
*/
@Override public Collection<V> values() {
return super.values();
}
private transient Map<R, Map<C, V>> rowMap;
@Override public Map<R, Map<C, V>> rowMap() {
Map<R, Map<C, V>> result = rowMap;
return (result == null) ? rowMap = createRowMap() : result;
}
Map<R, Map<C, V>> createRowMap() {
return new RowMap();
}
class RowMap extends ImprovedAbstractMap<R, Map<C, V>> {
@Override public boolean containsKey(Object key) {
return containsRow(key);
}
// performing cast only when key is in backing map and has the correct type
@Override public Map<C, V> get(Object key) {
return containsRow(key) ? row((R) key) : null;
}
@Override public Map<C, V> remove(Object key) {
return (key == null) ? null : backingMap.remove(key);
}
@Override protected Set<Entry<R, Map<C, V>>> createEntrySet() {
return new EntrySet();
}
class EntrySet extends TableSet<Entry<R, Map<C, V>>> {
@Override public Iterator<Entry<R, Map<C, V>>> iterator() {
return Maps.asMapEntryIterator(backingMap.keySet(), new Function<R, Map<C, V>>() {
@Override
public Map<C, V> apply(R rowKey) {
return row(rowKey);
}
});
}
@Override public int size() {
return backingMap.size();
}
@Override public boolean contains(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return entry.getKey() != null
&& entry.getValue() instanceof Map
&& Filter.safeContains(backingMap.entrySet(), entry);
}
return false;
}
@Override public boolean remove(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return entry.getKey() != null
&& entry.getValue() instanceof Map
&& backingMap.entrySet().remove(entry);
}
return false;
}
}
}
private transient ColumnMap columnMap;
@Override public Map<C, Map<R, V>> columnMap() {
ColumnMap result = columnMap;
return (result == null) ? columnMap = new ColumnMap() : result;
}
private class ColumnMap extends ImprovedAbstractMap<C, Map<R, V>> {
// The cast to C occurs only when the key is in the map, implying that it
// has the correct type.
@Override public Map<R, V> get(Object key) {
return containsColumn(key) ? column((C) key) : null;
}
@Override public boolean containsKey(Object key) {
return containsColumn(key);
}
@Override public Map<R, V> remove(Object key) {
return containsColumn(key) ? removeColumn(key) : null;
}
@Override public Set<Entry<C, Map<R, V>>> createEntrySet() {
return new ColumnMapEntrySet();
}
@Override public Set<C> keySet() {
return columnKeySet();
}
@Override Collection<Map<R, V>> createValues() {
return new ColumnMapValues();
}
class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> {
@Override public Iterator<Entry<C, Map<R, V>>> iterator() {
return Maps.asMapEntryIterator(columnKeySet(), new Function<C, Map<R, V>>() {
@Override
public Map<R, V> apply(C columnKey) {
return column(columnKey);
}
});
}
@Override public int size() {
return columnKeySet().size();
}
@Override public boolean contains(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
if (containsColumn(entry.getKey())) {
// The cast to C occurs only when the key is in the map, implying
// that it has the correct type.
C columnKey = (C) entry.getKey();
return get(columnKey).equals(entry.getValue());
}
}
return false;
}
@Override public boolean remove(Object obj) {
if (contains(obj)) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
removeColumn(entry.getKey());
return true;
}
return false;
}
@Override public boolean removeAll(Collection<?> c) {
/*
* We can't inherit the normal implementation (which calls
* Sets.removeAllImpl(Set, *Collection*) because, under some
* circumstances, it attempts to call columnKeySet().iterator().remove,
* which is unsupported.
*/
checkNotNull(c);
return Sets.removeAllImpl(this, c.iterator());
}
@Override public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
if (!c.contains(Maps.immutableEntry(columnKey, column(columnKey)))) {
removeColumn(columnKey);
changed = true;
}
}
return changed;
}
}
private class ColumnMapValues extends Maps.Values<C, Map<R, V>> {
ColumnMapValues() {
super(ColumnMap.this);
}
@Override public boolean remove(Object obj) {
for (Entry<C, Map<R, V>> entry : ColumnMap.this.entrySet()) {
if (entry.getValue().equals(obj)) {
removeColumn(entry.getKey());
return true;
}
}
return false;
}
@Override public boolean removeAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
if (c.contains(column(columnKey))) {
removeColumn(columnKey);
changed = true;
}
}
return changed;
}
@Override public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
if (!c.contains(column(columnKey))) {
removeColumn(columnKey);
changed = true;
}
}
return changed;
}
}
}
private static final long serialVersionUID = 0;
}

View file

@ -1,291 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* A collection that associates an ordered pair of keys, called a row key and a
* column key, with a single value. A table may be sparse, with only a small
* fraction of row key / column key pairs possessing a corresponding value.
*
* <p>The mappings corresponding to a given row key may be viewed as a {@link
* Map} whose keys are the columns. The reverse is also available, associating a
* column with a row key / value map. Note that, in some implementations, data
* access by column key may have fewer supported operations or worse performance
* than data access by row key.
*
* <p>The methods returning collections or maps always return views of the
* underlying table. Updating the table can change the contents of those
* collections, and updating the collections will change the table.
*
* <p>All methods that modify the table are optional, and the views returned by
* the table may or may not be modifiable. When modification isn't supported,
* those methods will throw an {@link UnsupportedOperationException}.
*
* <p>See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
* {@code Table}</a>.
*
* @author Jared Levy
* @param <R> the type of the table row keys
* @param <C> the type of the table column keys
* @param <V> the type of the mapped values
* @since 7.0
*/
public interface Table<R, C, V> {
// TODO(jlevy): Consider adding methods similar to ConcurrentMap methods.
// Accessors
/**
* Returns {@code true} if the table contains a mapping with the specified
* row and column keys.
*
* @param rowKey key of row to search for
* @param columnKey key of column to search for
*/
boolean contains(Object rowKey, Object columnKey);
/**
* Returns {@code true} if the table contains a mapping with the specified
* row key.
*
* @param rowKey key of row to search for
*/
boolean containsRow(Object rowKey);
/**
* Returns {@code true} if the table contains a mapping with the specified
* column.
*
* @param columnKey key of column to search for
*/
boolean containsColumn(Object columnKey);
/**
* Returns {@code true} if the table contains a mapping with the specified
* value.
*
* @param value value to search for
*/
boolean containsValue(Object value);
/**
* Returns the value corresponding to the given row and column keys, or
* {@code null} if no such mapping exists.
*
* @param rowKey key of row to search for
* @param columnKey key of column to search for
*/
V get(Object rowKey, Object columnKey);
/** Returns {@code true} if the table contains no mappings. */
boolean isEmpty();
/**
* Returns the number of row key / column key / value mappings in the table.
*/
int size();
/**
* Compares the specified object with this table for equality. Two tables are
* equal when their cell views, as returned by {@link #cellSet}, are equal.
*/
@Override
boolean equals(Object obj);
/**
* Returns the hash code for this table. The hash code of a table is defined
* as the hash code of its cell view, as returned by {@link #cellSet}.
*/
@Override
int hashCode();
// Mutators
/** Removes all mappings from the table. */
void clear();
/**
* Associates the specified value with the specified keys. If the table
* already contained a mapping for those keys, the old value is replaced with
* the specified value.
*
* @param rowKey row key that the value should be associated with
* @param columnKey column key that the value should be associated with
* @param value value to be associated with the specified keys
* @return the value previously associated with the keys, or {@code null} if
* no mapping existed for the keys
*/
V put(R rowKey, C columnKey, V value);
/**
* Copies all mappings from the specified table to this table. The effect is
* equivalent to calling {@link #put} with each row key / column key / value
* mapping in {@code table}.
*
* @param table the table to add to this table
*/
void putAll(Table<? extends R, ? extends C, ? extends V> table);
/**
* Removes the mapping, if any, associated with the given keys.
*
* @param rowKey row key of mapping to be removed
* @param columnKey column key of mapping to be removed
* @return the value previously associated with the keys, or {@code null} if
* no such value existed
*/
V remove(Object rowKey, Object columnKey);
// Views
/**
* Returns a view of all mappings that have the given row key. For each row
* key / column key / value mapping in the table with that row key, the
* returned map associates the column key with the value. If no mappings in
* the table have the provided row key, an empty map is returned.
*
* <p>Changes to the returned map will update the underlying table, and vice
* versa.
*
* @param rowKey key of row to search for in the table
* @return the corresponding map from column keys to values
*/
Map<C, V> row(R rowKey);
/**
* Returns a view of all mappings that have the given column key. For each row
* key / column key / value mapping in the table with that column key, the
* returned map associates the row key with the value. If no mappings in the
* table have the provided column key, an empty map is returned.
*
* <p>Changes to the returned map will update the underlying table, and vice
* versa.
*
* @param columnKey key of column to search for in the table
* @return the corresponding map from row keys to values
*/
Map<R, V> column(C columnKey);
/**
* Returns a set of all row key / column key / value triplets. Changes to the
* returned set will update the underlying table, and vice versa. The cell set
* does not support the {@code add} or {@code addAll} methods.
*
* @return set of table cells consisting of row key / column key / value
* triplets
*/
Set<Cell<R, C, V>> cellSet();
/**
* Returns a set of row keys that have one or more values in the table.
* Changes to the set will update the underlying table, and vice versa.
*
* @return set of row keys
*/
Set<R> rowKeySet();
/**
* Returns a set of column keys that have one or more values in the table.
* Changes to the set will update the underlying table, and vice versa.
*
* @return set of column keys
*/
Set<C> columnKeySet();
/**
* Returns a collection of all values, which may contain duplicates. Changes
* to the returned collection will update the underlying table, and vice
* versa.
*
* @return collection of values
*/
Collection<V> values();
/**
* Returns a view that associates each row key with the corresponding map from
* column keys to values. Changes to the returned map will update this table.
* The returned map does not support {@code put()} or {@code putAll()}, or
* {@code setValue()} on its entries.
*
* <p>In contrast, the maps returned by {@code rowMap().get()} have the same
* behavior as those returned by {@link #row}. Those maps may support {@code
* setValue()}, {@code put()}, and {@code putAll()}.
*
* @return a map view from each row key to a secondary map from column keys to
* values
*/
Map<R, Map<C, V>> rowMap();
/**
* Returns a view that associates each column key with the corresponding map
* from row keys to values. Changes to the returned map will update this
* table. The returned map does not support {@code put()} or {@code putAll()},
* or {@code setValue()} on its entries.
*
* <p>In contrast, the maps returned by {@code columnMap().get()} have the
* same behavior as those returned by {@link #column}. Those maps may support
* {@code setValue()}, {@code put()}, and {@code putAll()}.
*
* @return a map view from each column key to a secondary map from row keys to
* values
*/
Map<C, Map<R, V>> columnMap();
/**
* Row key / column key / value triplet corresponding to a mapping in a table.
*
* @since 7.0
*/
interface Cell<R, C, V> {
/**
* Returns the row key of this cell.
*/
R getRowKey();
/**
* Returns the column key of this cell.
*/
C getColumnKey();
/**
* Returns the value of this cell.
*/
V getValue();
/**
* Compares the specified object with this cell for equality. Two cells are
* equal when they have equal row keys, column keys, and values.
*/
@Override
boolean equals(Object obj);
/**
* Returns the hash code of this cell.
*
* <p>The hash code of a table cell is equal to {@link
* Objects#hashCode}{@code (e.getRowKey(), e.getColumnKey(), e.getValue())}.
*/
@Override
int hashCode();
}
}

View file

@ -1,53 +0,0 @@
/*
* Copyright (C) 2012 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 game.collect;
import static game.collect.Preconditions.checkNotNull;
import java.util.Iterator;
/**
* An iterator that transforms a backing iterator; for internal use. This avoids
* the object overhead of constructing a {@link Function} for internal methods.
*
* @author Louis Wasserman
*/
abstract class TransformedIterator<F, T> implements Iterator<T> {
final Iterator<? extends F> backingIterator;
TransformedIterator(Iterator<? extends F> backingIterator) {
this.backingIterator = checkNotNull(backingIterator);
}
abstract T transform(F from);
@Override
public final boolean hasNext() {
return backingIterator.hasNext();
}
@Override
public final T next() {
return transform(backingIterator.next());
}
@Override
public final void remove() {
backingIterator.remove();
}
}

View file

@ -1,43 +0,0 @@
/*
* Copyright (C) 2008 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 game.collect;
import java.util.Iterator;
/**
* An iterator that does not support {@link #remove}.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
public abstract class UnmodifiableIterator<E> implements Iterator<E> {
/** Constructor for use by subclasses. */
protected UnmodifiableIterator() {}
/**
* Guaranteed to throw an exception and leave the underlying data unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void remove() {
throw new UnsupportedOperationException();
}
}

View file

@ -1,53 +0,0 @@
/*
* Copyright (C) 2010 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 game.collect;
import java.util.ListIterator;
/**
* A list iterator that does not support {@link #remove}, {@link #add}, or
* {@link #set}.
*
* @since 7.0
* @author Louis Wasserman
*/
abstract class UnmodifiableListIterator<E>
extends UnmodifiableIterator<E> implements ListIterator<E> {
/** Constructor for use by subclasses. */
protected UnmodifiableListIterator() {}
/**
* Guaranteed to throw an exception and leave the underlying data unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final void add(E e) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the underlying data unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated @Override public final void set(E e) {
throw new UnsupportedOperationException();
}
}

View file

@ -2,7 +2,8 @@ package game.color;
import java.util.Map;
import game.collect.Maps;
import com.google.common.collect.Maps;
import game.properties.IStringSerializable;
public enum DyeColor implements IStringSerializable

View file

@ -2,7 +2,7 @@ package game.command;
import java.util.List;
import game.collect.Lists;
import com.google.common.collect.Lists;
public abstract class ArgumentParser {
public static String[][] splitString(String str) {

View file

@ -3,8 +3,8 @@ package game.command;
import java.util.List;
import java.util.Map;
import game.collect.Lists;
import game.collect.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class CachedExecutable {
private final Executable executable;

View file

@ -2,7 +2,7 @@ package game.command;
import java.util.Map;
import game.collect.Maps;
import com.google.common.collect.Maps;
public class EnumParser extends DefaultingParser {
private final Map<String, Object> lookup = Maps.newHashMap();

View file

@ -3,8 +3,9 @@ package game.command;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
import game.block.Block;
import game.collect.Maps;
import game.entity.Entity;
import game.entity.npc.EntityNPC;
import game.entity.types.EntityLiving;

View file

@ -4,9 +4,10 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import game.Server;
import game.collect.Lists;
import game.collect.Maps;
import game.color.TextColor;
public class ScriptEnvironment {

View file

@ -2,8 +2,8 @@ package game.command;
import java.util.Map;
import game.collect.Lists;
import game.collect.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public abstract class ScriptExecutable implements Executable {
private final String name;

View file

@ -1,6 +1,6 @@
package game.command;
import java.util.function.Predicate;
import com.google.common.base.Predicate;
public class StringParser extends DefaultingParser {
private final boolean allowEmpty;

View file

@ -2,8 +2,9 @@ package game.command;
import java.util.List;
import com.google.common.collect.Lists;
import game.Server;
import game.collect.Lists;
import game.dimension.Dimension;
import game.world.WorldServer;

View file

@ -2,7 +2,7 @@ package game.dimension;
import java.util.Map;
import game.collect.Maps;
import com.google.common.collect.Maps;
public enum DimType {
STAR("star", "Stern %s", true, false, false, false, false, false, true),

View file

@ -4,11 +4,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import game.biome.Biome;
import game.block.LeavesType;
import game.collect.Lists;
import game.collect.Maps;
import game.collect.Sets;
import game.init.BlockRegistry;
import game.init.Blocks;
import game.init.MetalType;

View file

@ -2,7 +2,7 @@ package game.dimension;
import java.util.Set;
import game.collect.Sets;
import com.google.common.collect.Sets;
public final class Domain extends Nameable implements Comparable<Domain> {
public final String id;

View file

@ -2,7 +2,7 @@ package game.dimension;
import java.util.Set;
import game.collect.Sets;
import com.google.common.collect.Sets;
public final class Galaxy extends Nameable implements Comparable<Galaxy> {
public final String id;

View file

@ -2,7 +2,7 @@ package game.dimension;
import java.util.Set;
import game.collect.Sets;
import com.google.common.collect.Sets;
public final class Planet extends Dimension {
private final Set<Moon> moons = Sets.newTreeSet();

Some files were not shown because too many files have changed in this diff Show more