001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.io; 019 020import java.io.DataInput; 021import java.io.DataOutput; 022import java.io.IOException; 023import java.util.Collection; 024import java.util.HashMap; 025import java.util.Map; 026import java.util.Set; 027 028import org.apache.hadoop.classification.InterfaceAudience; 029import org.apache.hadoop.classification.InterfaceStability; 030import org.apache.hadoop.util.ReflectionUtils; 031 032/** 033 * A Writable Map. 034 */ 035@InterfaceAudience.Public 036@InterfaceStability.Stable 037public class MapWritable extends AbstractMapWritable 038 implements Map<Writable, Writable> { 039 040 private Map<Writable, Writable> instance; 041 042 /** Default constructor. */ 043 public MapWritable() { 044 super(); 045 this.instance = new HashMap<Writable, Writable>(); 046 } 047 048 /** 049 * Copy constructor. 050 * 051 * @param other the map to copy from 052 */ 053 public MapWritable(MapWritable other) { 054 this(); 055 copy(other); 056 } 057 058 /** {@inheritDoc} */ 059 public void clear() { 060 instance.clear(); 061 } 062 063 /** {@inheritDoc} */ 064 public boolean containsKey(Object key) { 065 return instance.containsKey(key); 066 } 067 068 /** {@inheritDoc} */ 069 public boolean containsValue(Object value) { 070 return instance.containsValue(value); 071 } 072 073 /** {@inheritDoc} */ 074 public Set<Map.Entry<Writable, Writable>> entrySet() { 075 return instance.entrySet(); 076 } 077 078 /** {@inheritDoc} */ 079 public boolean equals(Object obj) { 080 if (this == obj) { 081 return true; 082 } 083 084 if (obj instanceof MapWritable) { 085 Map map = (Map) obj; 086 if (size() != map.size()) { 087 return false; 088 } 089 090 return entrySet().equals(map.entrySet()); 091 } 092 093 return false; 094 } 095 096 /** {@inheritDoc} */ 097 public Writable get(Object key) { 098 return instance.get(key); 099 } 100 101 /** {@inheritDoc} */ 102 public int hashCode() { 103 return 1 + this.instance.hashCode(); 104 } 105 106 /** {@inheritDoc} */ 107 public boolean isEmpty() { 108 return instance.isEmpty(); 109 } 110 111 /** {@inheritDoc} */ 112 public Set<Writable> keySet() { 113 return instance.keySet(); 114 } 115 116 /** {@inheritDoc} */ 117 @SuppressWarnings("unchecked") 118 public Writable put(Writable key, Writable value) { 119 addToMap(key.getClass()); 120 addToMap(value.getClass()); 121 return instance.put(key, value); 122 } 123 124 /** {@inheritDoc} */ 125 public void putAll(Map<? extends Writable, ? extends Writable> t) { 126 for (Map.Entry<? extends Writable, ? extends Writable> e: t.entrySet()) { 127 put(e.getKey(), e.getValue()); 128 } 129 } 130 131 /** {@inheritDoc} */ 132 public Writable remove(Object key) { 133 return instance.remove(key); 134 } 135 136 /** {@inheritDoc} */ 137 public int size() { 138 return instance.size(); 139 } 140 141 /** {@inheritDoc} */ 142 public Collection<Writable> values() { 143 return instance.values(); 144 } 145 146 // Writable 147 148 /** {@inheritDoc} */ 149 @Override 150 public void write(DataOutput out) throws IOException { 151 super.write(out); 152 153 // Write out the number of entries in the map 154 155 out.writeInt(instance.size()); 156 157 // Then write out each key/value pair 158 159 for (Map.Entry<Writable, Writable> e: instance.entrySet()) { 160 out.writeByte(getId(e.getKey().getClass())); 161 e.getKey().write(out); 162 out.writeByte(getId(e.getValue().getClass())); 163 e.getValue().write(out); 164 } 165 } 166 167 /** {@inheritDoc} */ 168 @SuppressWarnings("unchecked") 169 @Override 170 public void readFields(DataInput in) throws IOException { 171 super.readFields(in); 172 173 // First clear the map. Otherwise we will just accumulate 174 // entries every time this method is called. 175 this.instance.clear(); 176 177 // Read the number of entries in the map 178 179 int entries = in.readInt(); 180 181 // Then read each key/value pair 182 183 for (int i = 0; i < entries; i++) { 184 Writable key = (Writable) ReflectionUtils.newInstance(getClass( 185 in.readByte()), getConf()); 186 187 key.readFields(in); 188 189 Writable value = (Writable) ReflectionUtils.newInstance(getClass( 190 in.readByte()), getConf()); 191 192 value.readFields(in); 193 instance.put(key, value); 194 } 195 } 196}