在java中,除了实现定制的equals()和hashCode()之外,是否可以制作类似Comparator的东西
我有一个对象数组,我想将它与另一个对象数组连接起来,除了具有相同id的对象。对象在系统中的许多地方使用,并且没有实现哈希代码或相等值。所以我不想实现在java中,除了实现定制的equals()和hashCode()之外,是否可以制作类似Comparator的东西,java,collections,equals,hashcode,Java,Collections,Equals,Hashcode,我有一个对象数组,我想将它与另一个对象数组连接起来,除了具有相同id的对象。对象在系统中的许多地方使用,并且没有实现哈希代码或相等值。所以我不想实现hashCode()和equals(),因为我害怕破坏系统中使用这些对象的某个地方,我对此一无所知 我想将所有这些对象放在一个集合中,但不知何故使这些对象使用自定义的hashCode()和equals()。类似于自定义比较器的东西,但是对于equals。是的,这样做是可能的。但它不允许您将对象放入HashMap、HashSet等中。这是因为标准集合类
hashCode()
和equals()
,因为我害怕破坏系统中使用这些对象的某个地方,我对此一无所知
我想将所有这些对象放在一个集合中,但不知何故使这些对象使用自定义的
hashCode()
和equals()
。类似于自定义比较器的东西,但是对于equals。是的,这样做是可能的。但它不允许您将对象放入HashMap、HashSet等中。这是因为标准集合类希望键对象提供equals
和hashCode
方法。(这就是他们设计的工作方式…)
备选方案:
equals
和hashCode
实现equals
和hashCode
重写另一方面,当前的实现可能有一些真实(或想象)的性能原因;e、 减少内存使用。在这种情况下,您可能应该编写一组helper方法来执行诸如连接两个表示为数组的集合之类的操作 在这里需要帮助吗?TreeSet实际上使用compare/compareTo执行排序和基于集合的行为,并允许您定义自定义比较器以供i使用 当然,您可以创建一些外部对象,提供相等比较和哈希代码。但是Java的内置集合不使用这样的对象进行比较/查找 我曾经在我的软件包集合中创建过这样的界面(刚刚翻译成英文):
使用比较器进行重复数据消除串联不会成功。大概你想做这样的事情:
List<Object> list = new ArrayList<Object>();
list.addAll( a );
list.addAll( b );
Collections.sort( list, new MyCustomComparator() );
List List=new ArrayList();
列表。添加全部(a);
列表。添加全部(b);
Collections.sort(list,新的MyCustomComparator());
问题是比较器不仅需要比较相等/不相等,还需要比较相对顺序。给定不相等的对象x和y,必须回答其中一个是否大于另一个。您将无法这样做,因为您实际上并没有尝试比较对象。如果您没有给出一致的答案,您将把排序算法发送到一个无限循环中
我确实有一个解决办法给你。Java有一个名为LinkedHashSet的类,其优点是不允许插入重复项,但保持插入顺序。与其实现一个比较器,不如实现一个包装器类来保存实际对象并实现hashCode/equals 90%的时候,当用户想要一个等价关系时,已经有了一个更直接的解决方案。您想仅基于ID对一组内容进行重复数据消除吗?你能不能把它们都放到一个以ID为键的映射中,然后得到它的
values()
集合?是你要寻找的概念。它是一个策略接口,允许您定义equals和hashcode的自定义实现
public interface HashingStrategy<E>
{
int computeHashCode(E object);
boolean equals(E object1, E object2);
}
下面是如何使用HashingStrategy设置并使用统一网络
java.util.Set<Data> set =
new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(new Data(1)));
// contains returns true even without hashcode and equals
Assert.assertTrue(set.contains(new Data(1)));
// Second call to add() doesn't do anything and returns false
Assert.assertFalse(set.add(new Data(1)));
java.util.Set=
新的UnifiedSetWithHashingStrategy(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(新数据(1));
//包含返回true,即使没有hashcode和equals
Assert.assertTrue(set.contains)(新数据(1));
//对add()的第二次调用不执行任何操作并返回false
Assert.assertFalse(set.add(新数据(1));
为什么不直接使用地图
UnifiedSetWithHashingStrategy
使用了UnifiedMap
的一半内存,以及HashMap
的四分之一内存。有时你没有一个方便的键,必须创建一个合成键,比如元组。这会浪费更多的内存
我们如何执行查找?请记住,集合具有contains()
,但不具有get()
UnifiedSetWithHashingStrategy
除了实现MutableSet
之外,还实现了get()
的一种形式
注意:我是Eclipse集合的提交者。刚刚遇到这个问题,并制定了一个简单的解决方案。不确定它的内存密集程度;我相信人们可以不断完善它
当比较器返回0时,元素匹配
public static <E> Set<E> filterSet(Set<E> set, Comparator<E> comparator){
Set<E> output = new HashSet<E>();
for(E eIn : set){
boolean add = true;
for(E eOut : output){
if(comparator.compare(eIn, eOut) == 0){
add = false;
break;
}
}
if(add) output.add(eIn);
}
return output;
}
使用番石榴:
等价=新等价(){
@凌驾
受保护布尔不等价(TA,TB){
返回CustomComparator.equals(a,b);
}
@凌驾
受保护的int-doHash(T项){
返回CustomHashCodeGenerator.hashCode(项);
}
};
List items=getItems();
Set setWithWrappedObjects=items.stream()
.map(项目->等价性.wrap(项目))
.collect(收集器.toSet());
也许你需要创建一个包装类来实现equals和hashCode。我做不到,如果你担心
public class Data
{
private final int id;
public Data(int id)
{
this.id = id;
}
public int getId()
{
return id;
}
// No equals or hashcode
}
java.util.Set<Data> set =
new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(new Data(1)));
// contains returns true even without hashcode and equals
Assert.assertTrue(set.contains(new Data(1)));
// Second call to add() doesn't do anything and returns false
Assert.assertFalse(set.add(new Data(1)));
public static <E> Set<E> filterSet(Set<E> set, Comparator<E> comparator){
Set<E> output = new HashSet<E>();
for(E eIn : set){
boolean add = true;
for(E eOut : output){
if(comparator.compare(eIn, eOut) == 0){
add = false;
break;
}
}
if(add) output.add(eIn);
}
return output;
}
filtered = Misc.filterSet(filtered, (a, b) -> a.sameFile(b) ? 0 : 1);