简体   繁体   English

有没有办法按流或其他方式对具有 2 个类的数组列表进行排序?

[英]Is there any way to sort an arraylist which have 2 classes by stream or whatever?

I know this question might be ridiculous complicated but this is something I must achieve... Assume I have a list of 'entities':我知道这个问题可能是荒谬的复杂,但这是我必须实现的目标......假设我有一个“实体”列表:

  //they are all in the PlayGround class
  public static interface Entity{
    void turn(PlayGround g);
    int x();
    int y();
    int radius();
    }
 
  public ArrayList<Entity> entities(){return entities;}
  ArrayList<Entity> entities=new ArrayList<>();

Then I have two subclasses rock and miner extends from Entity:然后我有两个子类岩石和矿工从实体扩展:

//Record is a new feature in Java14 which similar to create a new class with fields
@SuppressWarnings("preview")
record Rock(int x,int y, int radius) implements Entity, Comparable<Rock>{
  ...
  public int compareTo(Rock o) {return Integer.compare(radius,o.radius);}
  public int getRadius() {return radius;};
}

class Miner implements Entity{
  int x=100;int y=100;
  public int x(){return x;}
  public int y(){return y;}
  public int radius(){return 15;}
...
}

In that case, we can add elements like this:在这种情况下,我们可以添加这样的元素:

    var mg=new PlayGround();
    mg.entities().add(new Rock(200,200,50));
    mg.entities().add(new Rock(250,100,40));
    mg.entities().add(new Rock(200,350,80));
    mg.entities().add(new Miner()); 

However, I want to sort the Rock class in the Arraylist by the number of radius, in the example, the ArrayList will from[Rock(50), Rock(40), Rock(80), Miner()] to [Rock(80), Rock(50), Rock(40), Miner()].但是,我想按半径对Arraylist中的Rock类进行排序,在示例中,ArrayList将从[Rock(50), Rock(40), Rock(80), Miner()] 到 [Rock( 80),岩石(50),岩石(40),矿工()]。

From the former query I tried:从我尝试过的前一个查询中:

    var es = mg.entities();
    @SuppressWarnings("unchecked")
    ArrayList<Entity> ess = es.stream()
     .filter(Rock.class::isInstance)
     .map(Rock.class::cast)
     .sorted(Comparator.comparingInt(Rock::getRadius))
     .collect(Collectors 
             .toCollection(ArrayList::new));

But it only compares the rock class and filter Miner out in the result.但它只比较摇滚类并在结果中过滤掉 Miner。 Is there any way to achieve this?有没有办法实现这一目标? Thanks!谢谢!

There's no need to involve stream API.无需涉及流 API。

Your description of the problem is unclear.您对问题的描述不清楚。 As is supposed to happen with unclear tasks, it is not possible to write an unclear task in code, as computers require very specific instructions.正如不明确的任务应该发生的那样,不可能在代码中编写不明确的任务,因为计算机需要非常具体的指令。

The part that is unclear is: How do miners relate in this sorting algorithm of yours?不清楚的部分是:矿工在你的这个排序算法中是如何关联的?

Given [rock5,rock2,miner1,rock10] , there are many answers possible:鉴于[rock5,rock2,miner1,rock10] ,有很多可能的答案:

  • Leave the miners precisely where they are, and sort the rocks 'around' them.将矿工准确地留在他们所在的位置,并将“周围”的岩石分类。 becomes [rock2,rock5,miner1,rock10].变成 [rock2,rock5,miner1,rock10]。 This cannot be done in a short amount of code.这不能在短代码中完成。 It strongly suggests you don't want a single list of entities, but 2 lists (one of miners, one of entities).它强烈建议您不需要单个实体列表,而是 2 个列表(一个矿工,一个实体)。
  • Shift all the miners to the end: [rock2,rock5,rock10,miner1]将所有矿工移到最后: [rock2,rock5,rock10,miner1]
  • Shift all miners to the beginning: [miner1,rock2,rock5,rock10] .将所有矿工转移到开头: [miner1,rock2,rock5,rock10]

They're really all relatively tricky;它们确实都比较棘手; you can't do this by chaining a few Comparator::comparingInt and friends together.你不能通过将几个Comparator::comparingInt和朋友链接在一起来做到这一点。 You can write your own comparator that does the job, but note that technically comparators should remain consistent.您可以编写自己的比较器来完成这项工作,但请注意,从技术上讲,比较器应保持一致。 If a comparator says that 'a is below b', then if later asked about 'b and a', it MUST answer that 'b is above a', or things break in bizarre ways.如果比较器说“a 低于 b”,那么如果稍后询问“b 和 a”,它必须回答“b 高于 a”,否则事情会以奇怪的方式破裂。 That complicates matters, there isn't really a 'eh, whatever, don't try to order these things' option.这让事情变得复杂,真的没有“呃,无论如何,不​​要试图订购这些东西”的选项。 For sorting arraylists you can return 'I consider these at the same level', but note that TreeMap and TreeSet can't do that (any 2 things at the same level are considered the same key).对于排序数组列表,您可以返回“我认为它们处于同一级别”,但请注意TreeMapTreeSet不能这样做(同一级别的任何 2 件事都被认为是相同的键)。

That consistency is really a problem here.这种一致性在这里确实是一个问题。 If you say that all miners are at the same level of all rocks, you can't do that.如果你说所有矿工都在所有岩石的同一级别,你就不能那样做。 If rock1 is below rock2, but rock1 is at the same level as miner1, and miner1 is at the same level as miner2, boom, inconsistent.如果rock1低于rock2,但是rock1和miner1在同一水平,miner1和miner2在同一水平,boom,不一致。

So, your comparator has to get pretty complicated:因此,您的比较器必须变得非常复杂:

es.sort((a, b) -> {
    // miners are at the same level as each other.
    if (a instanceof Miner && b instanceof Miner) return 0;
    // miners are below all rocks
    if (a instanceof Miner) return -1;
    if (b instanceof Miner) return +1;
    // they're both rocks.
    return Integer.compare(((Rock) a).getRadius(), ((Rock b).getRadius());
});

that one would be consistent, and sorts all miners to the front.那将是一致的,并将所有矿工排序到前面。

If you want to sort 'around' the miners, I don't think list.sort (or Collections.sort) is capable of that, so fire up your favorite search engine and recreate TIMsort or quicksort or whatnot.如果您想对矿工进行“周围”排序,我认为 list.sort(或 Collections.sort)无法做到这一点,因此请启动您最喜欢的搜索引擎并重新创建 TIMsort 或 quicksort 或诸如此类的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何对类的ArrayList进行排序 - How to sort ArrayList of classes 我的模块化库的用户是否可以通过任何方式访问尚未导出的类? - Is there any way that users of my modular library are able to access classes which have not been exported? 有没有一种方法可以更改此选择排序方法以使其与任何类型的ArrayList一起使用? - Is there a way to alter this selection sort method to work with an ArrayList of any type? Arraylist中多个字符串的串联,可以具有任何值 - Concatenation of multiple Strings in Arraylist which can have any value 如何对扩展类的ArrayList进行排序? - How to sort ArrayList of extend classes? 排序包含子类类的arraylist - Sort arraylist that contains subclass classes 我想将2个不同的类添加到ArrayList中,定义ArrayList的最佳方法是什么? - I have 2 different classes that I want to add to an ArrayList what the best way to define the ArrayList? 有什么方法可以控制在wildfly中部署类的顺序 - Is there any way to control order in which classes are deployed in wildfly 有没有一种简单的方法可以以这种方式对数组列表进行排序? - Is there an easy way to sort an arraylist in this manner? 有什么方法可以强制类在Java中使用public static final字段? - Any way to force classes to have public static final field in Java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM