二维阵列/结构问题

时间:2011-03-18 16:02:58

标签: java oop

我需要在程序中组织灵活的数据结构方面的建议。 看,我要组织一下看起来像二维数组的数据结构 喜欢

double[][] arr = new double[10][10];

如果您需要设置或获取此数组的某些元素,您将编写类似

的内容
double x=arr[i,j]; // arr[i,j]=y;

其中i和j是int数字

但是在我的程序中我需要像

这样的东西
double k=arr[obj1,obj2]

其中obj1和obj2是对象

我有一个想法--HashMap可以解决我的问题

所以它看起来像

class Coordinates {
      Object1 obj1;
      Object2 obj2;
      //TODO override equals() method
      Coordinates(Object1 obj1, Object2 obj2) {
           this.obj1=obj1;
           this.obj2=obj2;
      }
}
...
HashMap<Coordinates, Double> semiTwoDimArray=new HashMap<Coordinates, Double>();

并且元素的设置和获取看起来像

semiTwoDimArray.put(new Coordinates(obj1, obj2), 3.14);

和获得可能是

double pi = semiTwoDimArray.get(new Coordinates(obj1, obj2));

但至于我: 1)这种实现在迭代行或列时存在问题(操作太多) 2)看起来不优雅

有人可以建议我更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

您可以将结构包装到一个类中,并提供漂亮而干净的get(Object,Object)set(Object,Object,double)方法。

这样,不雅的代码将包含在类中,每次访问结构时都不需要重复。

如果您发现原始选择不是最佳的,这也可以轻松更改基础数据结构。

答案 1 :(得分:0)

正如您所说,HashMap<Coordinate, Value>结构不允许您遍历行或列。

如果需要,那么这肯定不是正确的数据结构。

一些想法:

  • 使用嵌套地图:Map<RowKey, Map<ColumnKey, Value>>Map<ColumnKey, Map<RowKey, Value>> - 一个支持遍历行,另一个支持遍历列。也许你需要同时拥有这两种结构。

  • 使用一个地图进行直接访问,另外还有按行/列进行迭代的列表。

  • 使用为此目的而制作的数据结构(我现在可以想象一个2D-hashmap)。

首先,您需要列出您的需求,甚至可以分析有多少对象,每列和每行中有多少(性能特征将取决于此)。你有任意对象,还是某些关键类型的对象?这种类型可比吗?


以下是 aix 建议的示例界面:

package de.fencing_game.paul.examples;

import java.util.*;

/**
 * A map with two keys.
 *
 * @see java.util.Map
 *
 * @param <K1> the first key type.
 * @param <K2> the second key type.
 * @param <V> the value type.
 */
public interface Map2D<K1,K2,V> {

    /**
     * A pair of keys for our map.
     */
    public interface KeyPair<K1,K2> {
        public K1 getKey1();
        public K2 getKey2();
        /**
         * returns the hashCode of this entry.
         * The hashcode is defines as 
         * {@code  getKey1().hashCode() * 13 + getKey2().hashCode() * 17}
         * If one of these objects is {@code null}, replace 0 for
         * its hash code.
         */
        public int hashCode();

        /**
         * compares this entry to another object. An object {@code that} is
         * equal this entry, if and only if it is also an Map2D.KeyPair, and 
         * {@code
         *  this.getKey1().equals(that.getKey1()) &&
         *  this.getKey2().equals(that.getKey2());
         * }
         */
        public boolean equals(Object that);
    }


    /**
     * an entry in our map, consisting of two keys and a value.
     * @see Map.Entry
     */
    public interface Entry<K1,K2,V> {
        public K1 getKey1();
        public K2 getKey2();
        public V getValue();
        public V setValue(V val);
        /**
         * returns the hashCode of this entry.
         * The hashcode is defines as 
         * {@code  getKey1.hashCode() * 7 + getKey2().hashCode() * 3 +
         *         getValue().hashCode() * 5 }
         * If one of these objects is {@code null}, replace 0 for
         * its hash code.
         */
        public int hashCode();

        /**
         * compares this entry to another object. An object {@code that} is
         * equal this entry, if and only if it is also an Map2D.Entry, and 
         * {@code
         *  this.getKey1().equals(that.getKey1()) &&
         *  this.getKey2().equals(that.getKey2()) &&
         *  this.getValue().equals(that.getValue());
         * }
         */
        public boolean equals(Object that);
    }


    /**
     * the number of mappings in this map.
     */
    public int size();

    /**
     * returns true if this map is empty.
     */
    public boolean isEmpty();


    /**
     * returns true if this map contains a mapping for the specified key pair.
     */
    public boolean containsKeys(Object key1, Object key2);

    /**
     * returns true if this map contains a mapping with this
     * specified key as first key.
     */
    public boolean containsKey1(Object key1);
    /**
     * returns true if this map contains a mapping with this
     * specified key as second key.
     */
    public boolean containsKey2(Object key2);

    /**
     * returns true if this map contains a mapping with the
     * specified value.
     */
    public boolean containsValue(Object value);

    /**
     * retrieves an element from the map.
     * @return null if there is no such pair of keys, else the value.
     */
    public V get(K1 key1, K2 key2);

    /**
     * puts a new element in the map.
     * @return the old value, or null, if there was no such mapping.
     */
    public V put(K1 key1, K2 key2, V value);

    /**
     * removes a mapping from this map.
     */
    public V remove(Object key1, Object key2);

    /**
     * puts all mappings from the specified 2d-map into this map.
     */
    public void putAll(Map2D<? extends K1, ? extends K2, ? extends V> map);

    /**
     * clears this map.
     */
    public void clear();

    /**
     * returns a collection view of the values of this map.
     */
    public Collection<V> values();

    /**
     * returns a collection view of this map's entries.
     */
    public Set<Map2D.Entry<K1,K2,V>> entrySet();

    /**
     * returns a map view as a map of key-pairs to values.
     */
    public Map<KeyPair<K1,K2>, V> flattedMap();

    /**
     * returns a map view as a map of maps, by first key first.
     */
    public Map<K1, Map<K2, V>> projection1Map();

    /**
     * returns a map view as a map of maps, by second key first.
     */
    public Map<K2, Map<K1, V>> projection2Map();

    /**
     * compares this map with another object.
     * This Map2D is equal to another object only if it also is a Map2D
     * and these equivalent conditions hold:
     * <ul>
     *   <li>{@code this.entrySet().equals(that.entrySet())}</li>
     *   <li>{@code this.flattedMap().equals(that.flattedMap())}</li>
     *   <li>{@code this.projection1Map().equals(that.projection1Map())}</li>
     *   <li>{@code this.projection2Map().equals(that.projection2Map())}</li>
     * </ul>
     */
    public boolean equals(Object that);

    /**
     * The hashCode is defined as the {@link #entrySet()}{@code .hashCode()}.
     */
    public int hashCode();

}

我稍后会添加一些示例实现。