Java 查找列表中两个元素的所有组合的最有效方法

Java 查找列表中两个元素的所有组合的最有效方法,java,performance,foreach,Java,Performance,Foreach,所以我有三节课。一方面,存在点类: public class Point { public float x; public float y; // Every point has a list of connections to other points indicated // by their position in the list of points in the main class. public List<Integer> co

所以我有三节课。一方面,存在类:

public class Point {
    public float x;
    public float y;

    // Every point has a list of connections to other points indicated
    // by their position in the list of points in the main class.
    public List<Integer> connections = new ArrayList<>();

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
}
public class Line {
    public Point start;
    public Point end;

    public Line(Point start, Point end) {
        this.start = start;
        this.end = end;
    }
}
public class Combination {
    public Line a;
    public Line b;

    public Combination(Line a, Line b) {
        this.a = a;
        this.b = b;
    }
}
组合类:

public class Point {
    public float x;
    public float y;

    // Every point has a list of connections to other points indicated
    // by their position in the list of points in the main class.
    public List<Integer> connections = new ArrayList<>();

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
}
public class Line {
    public Point start;
    public Point end;

    public Line(Point start, Point end) {
        this.start = start;
        this.end = end;
    }
}
public class Combination {
    public Line a;
    public Line b;

    public Combination(Line a, Line b) {
        this.a = a;
        this.b = b;
    }
}
我想要一个方法返回所有可能的组合列表,这些组合基于从给定点生成的线。我目前的做法如下:

public static List<Combination> findCombinations(List<Point> points) {
    List<Combination> combinations = new ArrayList<>();
    List<Line> lines = new ArrayList<>();

    for (Point a : points) {
        for (int p : a.connections) {
            lines.add(new Line(a, points.get(p)));
        }
    }

    for (Line a : lines) {
        for (Line b : lines) {
            if (a == b) continue;
            combinations.add(new Combination(a, b));
        }
    }

    return combinations;
}
公共静态列表查找组合(列表点){
列表组合=新的ArrayList();
列表行=新的ArrayList();
对于(a点:点){
用于(int p:a.connections){
添加(新行(a,points.get(p));
}
}
用于(行a:行){
用于(b行:行){
如果(a==b)继续;
增加(新的组合(a,b));
}
}
收益组合;
}
我有一个包含点列表的基类。对于该类的每个实例,我只调用上面的方法一次。但是,会创建很多实例,这种方法会减慢过程

我需要找到组合,以便测试在每个
组合
实例中两条线(段)是否相交。我基本上想找到所有相交的线的组合。为了实现这一点,我需要得到这些组合,然后检查交叉点在哪里


交点的计算不是问题。

I此类由点和线(通常称为节点和边)构成的图形通常会动态迭代所需的组合。 因此,通常不应生成包含所有此类组合的显式列表。

如果你坚持创建所有的组合,没有比迭代所有组合更快的方法了。 (更新:如果您的任务是查找所有直线交点,则有更快的已知算法。此字段称为计算几何)

如果图形是固定的,您可以加快一点速度,这样在创建后它就不会再改变了。
在这种情况下,您可以更换

 public List<Integer> connections = new ArrayList<>();
这种优化通常需要两个步骤。使用ArrayList构建图形,然后在准备就绪后,使用
int[]

此外,你提到的是“效率”。特别是在这里,人们必须在内存效率(如嵌入式导航系统)和计算速度(如内存较多时)之间做出选择


您的解决方案和我的答案与计算速度有关。

如果目的是将新创建的行与所有其他行合并,您可以通过从新的
和所有以前的行合并创建
组合
来摆脱第二种结构。我不确定这会快多少(如果有的话),但我觉得在代码组织方面会好一点

public static List<Combination> findCombinations(final List<Line> lines, final List<Point> points) {
    final List<Combination> combinations = new ArrayList<>();

    for (Point a : points) {
        for (int p : a.connections) {
            Line l = new Line(a, points.get(p));
            for(int i=0; i<lines.size(); i++){
                combinations.add(new Combination(lines.get(i),l));
            }
            lines.add(l);
        }
    }

    return combinations;
}
公共静态列表查找组合(最终列表行、最终列表点){
最终列表组合=新的ArrayList();
对于(a点:点){
用于(int p:a.connections){
第l行=新行(a,points.get(p));

对于(int i=0;我认为您更希望
继续
而不是
中断
,因为这不会产生所有组合。@JonK在这种情况下,可以使用
=
,因为您在同一列表上迭代了两次,并且确实只希望避免拾取同一元素两次。换句话说,您希望创建一个组合列表包含穿过一个点的所有可能路径的国家。路径中包含点和引出线的最后一行。您是否使用Java 8?有助于了解lambdas是否是一种选择。您为什么不在前面提到这一点?您应该描述您要解决的任务,而不是显示您的实现。请用更多的d描述即将查找所有直线的所有交点?是否要查找所有点对点组合的所有交点?当前,现有直线未作为参数传递。如果我这样做,我将不得不在该方法之外进行另一个循环,这将更加嵌套,不是吗?不。从功能上讲,无论您是否是访问类成员或方法参数。行为应相同。将对象作为方法参数传递与访问全局参数相比,有轻微的性能优势。