Java 合并两个没有重复子类的ArrayList

Java 合并两个没有重复子类的ArrayList,java,arraylist,Java,Arraylist,鉴于: 如果我有两个ArrayList对象: public abstract class Cars {} ... public class Ford extends Cars {} ... public class Dodge extends Cars {} ... public class Volkswagen extends Cars {} ... 或 哪个实例进入合并列表并不重要 这可能吗?我搜索了一下,看到了一些关于使用Set的内容,但这似乎只能确保唯一引用,除非我严重误

鉴于:

如果我有两个ArrayList对象:

public abstract class Cars {}

...

public class Ford extends Cars {}

...

public class Dodge extends Cars {}

...

public class Volkswagen extends Cars {}

...

哪个实例进入合并列表并不重要


这可能吗?我搜索了一下,看到了一些关于使用Set的内容,但这似乎只能确保唯一引用,除非我严重误解了某些内容。

您可以将第一个列表中的所有元素添加到结果列表中(假设第一个列表中没有重复项)然后循环第二个列表,仅当第一个列表中没有相同类的实例时,才将元素添加到结果列表中

可能看起来像这样:

dealerMerged = ["ford1", "dodge2", "vw1"]
重写equals()将起作用,但不起作用 您可以将集合转换为
集合
(如@Arun在注释中所述)或在集合流上使用
distinct
操作,始终使集合具有显著性。但是请记住,这些方法使用
equal()
方法来实现这一点。因此,快速思考将覆盖
equals()
并返回其
类型。但是等等!如果这样做,您将使所有
Dodge
对象彼此相等,尽管它们具有不同的属性,如name
dodge1
dodge2
。在read world中,您可能不仅仅处理一项业务
equal()
方法还有很多其他意义。所以不要这样做

如果您考虑的是Java8方式,那么有状态过滤器是完美的 我们可以选择对级联流使用
过滤器
操作<代码>过滤器
操作非常简单。它接受一个谓词并决定接受或忽略哪个元素。这是一个常用的功能,你可以在所有的博客上找到它来解决这个问题

dealerMerged = dealer1;
boolean isAlreadyRepresented;
for (car2 : dealer2) {
    isAlreadyRepresented = false;
    for (car1 : dealer1) {
        if (car1.getClass().equals(car2.getClass())) {
            isAlreadyRepresented = true;
        }
    }
    if (!isAlreadyRepresented) {
        dealerMerged.add(car2);
    }
}
那么我们在这里到底做了什么?
  • 我们将2
    ArrayList
    flatmap
    连接起来,这将为我们提供一个合并元素流(如果您是stream API的新手,请参阅本文)
  • 然后,我们利用
    filter()
    操作,该操作通过返回谓词的
    distinctBy方法提供
  • 您可以看到,
    ConcurrentHashMap
    通过一个布尔标志来跟踪哪个元素满足谓词或不满足谓词
  • 谓词使用
    getClass()
    方法返回完整的类名,将元素区分为子类
  • 然后,我们可以
    收集
    或迭代过滤列表

尝试使用地图而不是列表。您可以尝试以下解决方案。这将允许您按类型放置汽车实例。因此,每个类始终只有一个条目(顺便说一句,这将是地图中的最新条目)

公共类cars集合{

Map只需使用对象的类作为映射中的键即可。这个Java stream示例正好做到了这一点:

public class CarsCollection {
    Map<Class<? extends Cars>, ? super Cars> coll = new HashMap<>();

    public <T extends Cars> void add(Class<T> cls, T obj) {
        coll.put(cls, obj);
    }
}

public class Temp {

    public static void main(String[] args)  {

        CarsCollection nos1 = new CarsCollection();

        cars.add(Ford.class, new Ford("ford1"));
        cars.add(Dodge.class, new Dodge("dodge1"));

        cars.add(Dodge.class, new Dodge("dodge2"));
        cars.add(Volkswagen.class, new Volkswagen("vw1"));

        System.out.println(cars);
    }

}
List merged=Stream.of(dealer1,dealer2)
.flatMap(集合::流)
.collect(Collectors.toMap(对象::getClass,函数.identity(),(c1,c2)->c1))
.values()
.stream().collect(Collectors.toList());

这是可能的,但在尝试之前您永远不会知道。Set将识别重复项,并且不会添加元素(如果存在),它使用equals和hashCode方法来识别重复项。您必须重写子类中的这些方法,并告诉您必须识别重复项的属性,否则它将根据地址检查重复项比如你说的独特参考想象在现实生活中我递给你两个袋子。每个袋子里都是随机的水果和蔬菜。我想让你给我一个袋子,里面有一个水果和一个蔬菜。不管它们是什么。你会怎么做?想想你会采取的步骤。然后把这些步骤翻译成代码。她说e是一个提示:不完全相关,但品牌通常不作为子类建模,而是作为属性建模
dealerMerged = dealer1;
boolean isAlreadyRepresented;
for (car2 : dealer2) {
    isAlreadyRepresented = false;
    for (car1 : dealer1) {
        if (car1.getClass().equals(car2.getClass())) {
            isAlreadyRepresented = true;
        }
    }
    if (!isAlreadyRepresented) {
        dealerMerged.add(car2);
    }
}
public static <T> Predicate<T> distinctBy(Function<? super T, ?> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
Stream.of(dealer1, dealer2)
        .flatMap(Collection::stream)
        .filter(distinctBy(Cars::getClass))
        .collect(Collectors.toList())
        .forEach(cars -> System.out.println(cars));
public class CarsCollection {
    Map<Class<? extends Cars>, ? super Cars> coll = new HashMap<>();

    public <T extends Cars> void add(Class<T> cls, T obj) {
        coll.put(cls, obj);
    }
}

public class Temp {

    public static void main(String[] args)  {

        CarsCollection nos1 = new CarsCollection();

        cars.add(Ford.class, new Ford("ford1"));
        cars.add(Dodge.class, new Dodge("dodge1"));

        cars.add(Dodge.class, new Dodge("dodge2"));
        cars.add(Volkswagen.class, new Volkswagen("vw1"));

        System.out.println(cars);
    }

}
List<Cars> merged = Stream.of(dealer1, dealer2)
                    .flatMap(Collection::stream)
                    .collect( Collectors.toMap( Object::getClass, Function.identity(), (c1, c2) -> c1 ) )
                    .values()
                        .stream().collect( Collectors.toList() );