This project has retired. For details please refer to its Attic page.
HashMultimapEdges xref
View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.giraph.edge;
20  
21  import com.google.common.collect.ArrayListMultimap;
22  import com.google.common.collect.UnmodifiableIterator;
23  
24  import org.apache.giraph.utils.EdgeIterables;
25  import org.apache.giraph.utils.Trimmable;
26  import org.apache.hadoop.io.Writable;
27  import org.apache.hadoop.io.WritableComparable;
28  
29  import java.io.DataInput;
30  import java.io.DataOutput;
31  import java.io.IOException;
32  import java.util.Iterator;
33  import java.util.Map;
34  
35  /**
36   * {@link OutEdges} implementation backed by an {@link ArrayListMultimap}.
37   * Parallel edges are allowed.
38   * Note: this implementation is optimized for fast mutations,
39   * but uses more space.
40   *
41   * @param <I> Vertex id
42   * @param <E> Edge value
43   */
44  public class HashMultimapEdges<I extends WritableComparable, E extends Writable>
45      extends ConfigurableOutEdges<I, E>
46      implements MultiRandomAccessOutEdges<I, E>, Trimmable {
47    /** Multimap from target vertex id to edge values. */
48    private ArrayListMultimap<I, E> edgeMultimap;
49  
50    @Override
51    public void initialize(Iterable<Edge<I, E>> edges) {
52      EdgeIterables.initialize(this, edges);
53    }
54  
55    /**
56     * Additional initialization method tailored to the underlying multimap
57     * implementation.
58     *
59     * @param expectedNeighbors Expected number of unique neighbors
60     * @param expectedEdgesPerNeighbor Expected number of edges per neighbor
61     */
62    public void initialize(int expectedNeighbors, int expectedEdgesPerNeighbor) {
63      edgeMultimap = ArrayListMultimap.create(expectedNeighbors,
64          expectedEdgesPerNeighbor);
65    }
66  
67    @Override
68    public void initialize(int capacity) {
69      // To be conservative in terms of space usage, we assume that the initial
70      // number of values per key is 1.
71      initialize(capacity, 1);
72    }
73  
74    @Override
75    public void initialize() {
76      edgeMultimap = ArrayListMultimap.create();
77    }
78  
79    @Override
80    public void add(Edge<I, E> edge) {
81      edgeMultimap.put(edge.getTargetVertexId(), edge.getValue());
82    }
83  
84    @Override
85    public void remove(I targetVertexId) {
86      edgeMultimap.removeAll(targetVertexId);
87    }
88  
89    @Override
90    public Iterable<E> getAllEdgeValues(I targetVertexId) {
91      return edgeMultimap.get(targetVertexId);
92    }
93  
94    @Override
95    public int size() {
96      return edgeMultimap.size();
97    }
98  
99    @Override
100   public Iterator<Edge<I, E>> iterator() {
101     // Returns an iterator that reuses objects.
102     return new UnmodifiableIterator<Edge<I, E>>() {
103       /** Wrapped map iterator. */
104       private Iterator<Map.Entry<I, E>> mapIterator =
105           edgeMultimap.entries().iterator();
106       /** Representative edge object. */
107       private ReusableEdge<I, E> representativeEdge =
108           getConf().createReusableEdge();
109 
110       @Override
111       public boolean hasNext() {
112         return mapIterator.hasNext();
113       }
114 
115       @Override
116       public Edge<I, E> next() {
117         Map.Entry<I, E> nextEntry = mapIterator.next();
118         representativeEdge.setTargetVertexId(nextEntry.getKey());
119         representativeEdge.setValue(nextEntry.getValue());
120         return representativeEdge;
121       }
122     };
123   }
124 
125   @Override
126   public void write(DataOutput out) throws IOException {
127     // We write both the total number of edges and the number of unique
128     // neighbors.
129     out.writeInt(edgeMultimap.size());
130     out.writeInt(edgeMultimap.keys().size());
131     for (Map.Entry<I, E> edge : edgeMultimap.entries()) {
132       edge.getKey().write(out);
133       edge.getValue().write(out);
134     }
135   }
136 
137   @Override
138   public void readFields(DataInput in) throws IOException {
139     // Given the total number of pairs and the number of unique neighbors,
140     // we are able to compute the average number of edges per neighbors.
141     int numEdges = in.readInt();
142     int numNeighbors = in.readInt();
143     initialize(numEdges, numNeighbors == 0 ? 0 : numEdges / numNeighbors);
144     for (int i = 0; i < numEdges; ++i) {
145       I targetVertexId = getConf().createVertexId();
146       targetVertexId.readFields(in);
147       E edgeValue = getConf().createEdgeValue();
148       edgeValue.readFields(in);
149       edgeMultimap.put(targetVertexId, edgeValue);
150     }
151   }
152 
153   @Override
154   public void trim() {
155     edgeMultimap.trimToSize();
156   }
157 }