为什么我无法在没有枚举的情况下从哈希集中检索项目?

2022-09-01 06:11:43

我正在寻找对HashSet设计师的见解。据我所知,我的问题同时适用于Java和C#HashSets,这让我认为它一定有一些很好的理由,尽管我自己想不出任何理由。

将项目插入哈希集后,为什么在没有枚举的情况下无法检索该项目,这几乎不是一个有效的操作?特别是因为HashSet是以支持高效检索的方式显式构建的。

让 Remove(x) 和 Contains(x) 返回要删除或包含的实际项目通常很有用。这不一定是我传递到 Remove(x) 或 Contains(x) 函数中的项目。当然,我想我可以通过HashMap达到同样的效果,但是当用一套完全有可能做到这一点时,为什么要浪费所有的空间和精力呢?

我可以理解,可能会有一些设计问题,即添加此功能将允许使用与它们在框架中的角色或未来角色不一致的HashSet,但是如果是这样,这些设计问题是什么?

编辑

要回答更多问题,以下是更多详细信息:

我正在使用具有重写哈希码,equals等的不可变引用类型来模拟C#中的值类型。假设该类型具有成员 A、B 和 C.哈希码、等于等仅依赖于 A 和 B。给定一些A和B,我希望能够从哈希集中检索该等效项并得到它的C。我将无法使用HashSet来做到这一点,但我至少想知道是否有任何充分的理由。伪代码如下:

public sealed class X{
 object A;
 object B;
 object extra;

 public int HashCode(){
  return A.hashCode() + B.hashCode();
 }

 public bool Equals(X obj){
  return obj.A == A && obj.B == B;
 }
}

hashset.insert(new X(1,2, extra1));
hashset.contains(new X(1,2)); //returns true, but I can't retrieve extra

答案 1

在.Net中,您可能正在寻找的是KeyedCollection http://msdn.microsoft.com/en-us/library/ms132438.aspx

你可以通过一些“通用”的聪明来规避每次重新实现这个抽象类的恶心。(请参阅 IKeyedObject'1。

注意:任何实现 IKeyedObject'1 的数据传输对象都应该有一个被覆盖的 GetHashCode 方法,只需返回此方法即可。Key.GetHashCode();平等也是如此...

我的基类库通常以如下内容结束:

public class KeyedCollection<TItem> : System.Collections.ObjectModel.KeyedCollection<TItem, TItem>
    where TItem : class
{
    public KeyedCollection() : base()
    {
    }

    public KeyedCollection(IEqualityComparer<TItem> comparer) : base(comparer)
    {
    }

    protected override TItem GetKeyForItem(TItem item)
    {
        return item;
    }
}

public class KeyedObjectCollection<TKey, TItem> : System.Collections.ObjectModel.KeyedCollection<TKey, TItem>
    where TItem : class, IKeyedObject<TKey>
    where TKey : struct
{
    public KeyedCollection() : base()
    {
    }

    protected override TItem GetKeyForItem(TItem item)
    {
        return item.Key;
    }
}

///<summary>
/// I almost always implement this explicitly so the only
/// classes that have access without some rigmarole
/// are generic collections built to be aware that an object
/// is keyed.
///</summary>
public interface IKeyedObject<TKey>
{
    TKey Key { get; }
}

答案 2

您是如何建议从哈希集中检索项目的?根据定义,集合不以任何方式排序,因此,没有索引可用于检索相关对象。

集合作为一个概念,用于测试包含,即所讨论的元素是否在哈希数据集中。如果您希望使用键值或索引从数据源中检索值,我建议您查看MapList

编辑:基于对原始问题的编辑的其他答案

Soonil,根据您的新信息,看起来您可能有兴趣将数据实现为Java枚举,类似于以下内容:

 public enum SoonilsDataType {
      A, B, C;

      // Just an example of what's possible
      public static SoonilsDataType getCompositeValue(SoonilsDataType item1,
           SoonilsDataType item2) {
           if (item1.equals(A) && 
                     item2.equals(B)) {
                return C;
           }
      }
 }

Enum 的自动继承 values(),它返回枚举的“set”中所有值的列表,您可以使用它与 Set 相同的方式测试包含。此外,因为它是一个完整的类,所以你可以定义新的静态方法来执行复合逻辑(就像我在示例代码中试图暗示的那样)。关于Enum的唯一一件事是,您无法在运行时添加新实例,这可能不是您想要的(尽管如果集合的数据大小在运行时不会增长,则Enum就是您想要的)。


推荐