我正在尝试在 Java(或 Groovy)中找到一种可以实现类似功能的数据结构:
MemberAdressableSetsSet mass = new MemberAdressableSetsSet();
mass.addSet(["a","b"]);
mass.addSet(["c","d","e"]);
mass.get("d").add("f");
String output = Arrays.toString(mass.get("e").toArray());
System.out.println(output); // [ "c", "d", "e", "f" ] (ordering irrelevant)
有这样的事情存在吗?如果没有,是否有一种方法可以使用普通的 Java 代码来实现类似的功能,并且不会让 CPU 或内存陷入数周的噩梦?
编辑:更严格
MemberAdressableSetsSet mass = new MemberAdressableSetsSet();
Set<String> s1 = new HashSet<String>();
s1.add("a");
Set<String> s2 = new HashSet<String>();
s2.add("c");s2.add("d");s2.add("e");
mass.addSet(s1);
mass.addSet(s2);
Set<String> s3 = new HashSet<String>();
s3.add("a");s3.add("z");
mass.addSet(s3);
/* s3 contains "a", which is already in a subset of mass, so:
* Either
* - does nothing and returns false or throws Exception
* - deletes "a" from its previous subset before adding s3
* => possibly returns the old subset
* => deletes the old subset if that leaves it empty
* => maybe requires an optional parameter to be set
* - removes "a" from the new subset before adding it
* => possibly returns the new subset that was actually added
* => does not add the new subset if purging it of overlap leaves it empty
* => maybe requires an optional parameter to be set
* - merges all sets that would end up overlapping
* - adds it with no overlap checks, but get("a") returns an array of all sets containing it
*/
mass.get("d").add("f");
String output = Arrays.toString(mass.get("e").toArray());
System.out.println(output); // [ "c", "d", "e", "f" ] (ordering irrelevant)
mass.get("d")
将返回Set<T>
在mass
其中包含 "d"
。类似于 get() 在 HashMap
中的工作原理:
HashMap<String,LinkedList<Integer>> map = new HashMap<>();
LinkedList<Integer> list = new LinkedList<>();
list.add(9);
map.put("d",list);
map.get("d").add(4);
map.get("d"); // returns a LinkedList with contents [9,4]
最佳答案
到目前为止我能想到的最好的方法如下:
import java.util.HashMap;
import java.util.Set;
public class MemberAdressableSetsSet {
private int next_id = 1;
private HashMap<Object,Integer> members = new HashMap();
private HashMap<Integer,Set> sets = new HashMap();
public boolean addSet(Set s) {
if (s.size()==0) return false;
for (Object member : s) {
if (members.get(member)!=null) return false;
}
sets.put(next_id,s);
for (Object member : s) {
members.put(member,next_id);
}
next_id++;
return true;
}
public boolean deleteSet(Object member) {
Integer id = members.get(member);
if (id==null) return false;
Set set = sets.get(id);
for (Object m : set) {
members.remove(m);
}
sets.remove(id);
return true;
}
public boolean addToSet(Object member, Object addition) {
Integer id = members.get(member);
if (id==null) throw new IndexOutOfBoundsException();
if (members.get(addition)!=null) return false;
sets.get(id).add(addition);
members.put(addition,id);
return true;
}
public boolean removeFromSet(Object member) {
Integer id = members.get(member);
if (id==null) return false;
Set s = sets.get(id);
if (s.size()==1) sets.remove(id);
else s.remove(member);
members.remove(member);
return true;
}
public Set getSetClone(Object member) {
Integer id = members.get(member);
if (id==null) throw new IndexOutOfBoundsException();
Set copy = new java.util.HashSet(sets.get(id));
return copy;
}
}
它有一些缺点:
- 集合无法直接访问,这使得所有
Set
无法访问显式定义的转换方法未公开的方法和属性,除非克隆是可接受的选项 - 类型信息丢失。
- 说一个
Set<Date>
已添加。
例如,它不会提示尝试添加File
反对该集合。
- 说一个
至少集合丢失的类型信息不会扩展到其成员:Set.contains()
尽管双方都已被类型化为Object
,但仍然完全按照预期工作。在与 contains()
进行比较之前。所以一组包含 (Object)3
当询问是否包含 (Object)3L
时,不会返回 true例如,反之亦然。
一组包含
block 引用>(Object)(new java.util.Date(10L))
当询问是否包含(Object)(new java.sql.Date(10L))
时将返回 true (反之亦然),但即使没有(Object)
也是如此。在前面,所以我想这就是“按预期工作” ́\_(ツ)_/́
关于java - 是否存在一个集合的集合,其中集合的任何成员都可以寻址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56744590/