为什么我不能在没有枚举的情况下从HashSet中检索项目?

soo*_*iln 33 c# java hashset

我正在寻找洞察HashSet设计师的头脑.据我所知,我的问题适用于Java和C#HashSets,让我觉得必须有一些很好的理由,尽管我自己也想不到.

在我将项目插入HashSet之后,为什么在没有枚举的情况下检索该项目是不可能的,几乎不是有效的操作?特别是因为HashSet以支持有效检索的方式显式构建.

使用Remove(x)和Contains(x)返回正在删除或包含的实际项目通常很有用.这不一定是我传递给Remove(x)或Contains(x)函数的项目.当然,我想我可以通过HashMap实现同样的效果,但是为什么在完全有可能用套装完成时却浪费了所有的空间和努力?

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

编辑

要回答更多问题,请参阅以下详细信息:

我使用带有重写的hashcode,equals等的不可变引用类型来模拟C#中的值类型.假设类型有成员A,B和C.Hashcode,equals等仅依赖于A和B.给定A和BI希望能够从hashset中检索该等效项并得到它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
Run Code Online (Sandbox Code Playgroud)

lea*_*eat 10

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

你可以通过一些"通用"的聪明来解决每次重新实现这个抽象类的肮脏.(见IKeyedObject`1.)

注意:任何实现IKeyedObject`1的数据传输对象都应该有一个重写的GetHashCode方法,只需返回this.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; }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*ter 9

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

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

编辑:基于编辑原始问题的附加答案

Soonil,基于您的新信息,看起来您可能有兴趣将您的数据实现为Java Enum,类似于:

 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;
           }
      }
 }
Run Code Online (Sandbox Code Playgroud)

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

  • @andresp我知道这已经很晚了,但是如果你知道你在可枚举集合中只有一个元素(包括`HashSet`)那么扩展方法`First()`和/或`Single()`就是你想要的/需要. (2认同)