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     */
018    package org.apache.hadoop.hdfs.util;
019    
020    import java.util.Arrays;
021    
022    import com.google.common.base.Preconditions;
023    
024    /**
025     * Similar to {@link EnumCounters} except that the value type is double.
026     *
027     * @param <E> the enum type
028     */
029    public class EnumDoubles<E extends Enum<E>> {
030      /** The class of the enum. */
031      private final Class<E> enumClass;
032      /** An array of doubles corresponding to the enum type. */
033      private final double[] doubles;
034    
035      /**
036       * Construct doubles for the given enum constants.
037       * @param enumClass the enum class.
038       */
039      public EnumDoubles(final Class<E> enumClass) {
040        final E[] enumConstants = enumClass.getEnumConstants();
041        Preconditions.checkNotNull(enumConstants);
042        this.enumClass = enumClass;
043        this.doubles = new double[enumConstants.length];
044      }
045      
046      /** @return the value corresponding to e. */
047      public final double get(final E e) {
048        return doubles[e.ordinal()];
049      }
050    
051      /** Negate all values. */
052      public final void negation() {
053        for(int i = 0; i < doubles.length; i++) {
054          doubles[i] = -doubles[i];
055        }
056      }
057      
058      /** Set e to the given value. */
059      public final void set(final E e, final double value) {
060        doubles[e.ordinal()] = value;
061      }
062    
063      /** Set the values of this object to that object. */
064      public final void set(final EnumDoubles<E> that) {
065        for(int i = 0; i < doubles.length; i++) {
066          this.doubles[i] = that.doubles[i];
067        }
068      }
069    
070      /** Reset all values to zero. */
071      public final void reset() {
072        for(int i = 0; i < doubles.length; i++) {
073          this.doubles[i] = 0.0;
074        }
075      }
076    
077      /** Add the given value to e. */
078      public final void add(final E e, final double value) {
079        doubles[e.ordinal()] += value;
080      }
081    
082      /** Add the values of that object to this. */
083      public final void add(final EnumDoubles<E> that) {
084        for(int i = 0; i < doubles.length; i++) {
085          this.doubles[i] += that.doubles[i];
086        }
087      }
088    
089      /** Subtract the given value from e. */
090      public final void subtract(final E e, final double value) {
091        doubles[e.ordinal()] -= value;
092      }
093    
094      /** Subtract the values of this object from that object. */
095      public final void subtract(final EnumDoubles<E> that) {
096        for(int i = 0; i < doubles.length; i++) {
097          this.doubles[i] -= that.doubles[i];
098        }
099      }
100    
101      @Override
102      public boolean equals(Object obj) {
103        if (obj == this) {
104          return true;
105        } else if (obj == null || !(obj instanceof EnumDoubles)) {
106          return false;
107        }
108        final EnumDoubles<?> that = (EnumDoubles<?>)obj;
109        return this.enumClass == that.enumClass
110            && Arrays.equals(this.doubles, that.doubles);
111      }
112    
113      @Override
114      public int hashCode() {
115        return Arrays.hashCode(doubles);
116      }
117    
118      @Override
119      public String toString() {
120        final E[] enumConstants = enumClass.getEnumConstants();
121        final StringBuilder b = new StringBuilder();
122        for(int i = 0; i < doubles.length; i++) {
123          final String name = enumConstants[i].name();
124          b.append(name).append("=").append(doubles[i]).append(", ");
125        }
126        return b.substring(0, b.length() - 2);
127      }
128    }