Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.giraph.edge; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.UnmodifiableIterator; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableComparable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Map; /** * {@link OutEdges} implementation backed by an {@link ArrayListMultimap}. * Parallel edges are allowed. * Note: this implementation is optimized for fast mutations, * but uses more space. * * @param <I> Vertex id * @param <E> Edge value */ public class HashMultimapEdges<I extends WritableComparable, E extends Writable> extends ConfigurableOutEdges<I, E> implements MultiRandomAccessOutEdges<I, E> { /** Multimap from target vertex id to edge values. */ private ArrayListMultimap<I, E> edgeMultimap; @Override public void initialize(Iterable<Edge<I, E>> edges) { // If the iterable is actually a collection, we can cheaply get the // size and initialize the hash-multimap with the expected capacity. if (edges instanceof Collection) { initialize(((Collection<Edge<I, E>>) edges).size()); } else { initialize(); } for (Edge<I, E> edge : edges) { add(edge); } } /** * Additional initialization method tailored to the underlying multimap * implementation. * * @param expectedNeighbors Expected number of unique neighbors * @param expectedEdgesPerNeighbor Expected number of edges per neighbor */ public void initialize(int expectedNeighbors, int expectedEdgesPerNeighbor) { edgeMultimap = ArrayListMultimap.create(expectedNeighbors, expectedEdgesPerNeighbor); } @Override public void initialize(int capacity) { // To be conservative in terms of space usage, we assume that the initial // number of values per key is 1. initialize(capacity, 1); } @Override public void initialize() { edgeMultimap = ArrayListMultimap.create(); } @Override public void add(Edge<I, E> edge) { edgeMultimap.put(edge.getTargetVertexId(), edge.getValue()); } @Override public void remove(I targetVertexId) { edgeMultimap.removeAll(targetVertexId); } @Override public Iterable<E> getAllEdgeValues(I targetVertexId) { return edgeMultimap.get(targetVertexId); } @Override public int size() { return edgeMultimap.size(); } @Override public Iterator<Edge<I, E>> iterator() { // Returns an iterator that reuses objects. return new UnmodifiableIterator<Edge<I, E>>() { /** Wrapped map iterator. */ private Iterator<Map.Entry<I, E>> mapIterator = edgeMultimap.entries().iterator(); /** Representative edge object. */ private ReusableEdge<I, E> representativeEdge = getConf().createReusableEdge(); @Override public boolean hasNext() { return mapIterator.hasNext(); } @Override public Edge<I, E> next() { Map.Entry<I, E> nextEntry = mapIterator.next(); representativeEdge.setTargetVertexId(nextEntry.getKey()); representativeEdge.setValue(nextEntry.getValue()); return representativeEdge; } }; } @Override public void write(DataOutput out) throws IOException { // We write both the total number of edges and the number of unique // neighbors. out.writeInt(edgeMultimap.size()); out.writeInt(edgeMultimap.keys().size()); for (Map.Entry<I, E> edge : edgeMultimap.entries()) { edge.getKey().write(out); edge.getValue().write(out); } } @Override public void readFields(DataInput in) throws IOException { // Given the total number of pairs and the number of unique neighbors, // we are able to compute the average number of edges per neighbors. int numEdges = in.readInt(); int numNeighbors = in.readInt(); initialize(numEdges, numNeighbors == 0 ? 0 : numEdges / numNeighbors); for (int i = 0; i < numEdges; ++i) { I targetVertexId = getConf().createVertexId(); targetVertexId.readFields(in); E edgeValue = getConf().createEdgeValue(); edgeValue.readFields(in); edgeMultimap.put(targetVertexId, edgeValue); } } }