首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按照条件将数组划分为子数组的最优雅的方法

按照条件将数组划分为子数组的最优雅的方法
EN

Stack Overflow用户
提问于 2014-05-19 15:50:22
回答 4查看 195关注 0票数 0

非常大的数组:{o1,o2,o3,.,o100000}。在某些情况下,元素序列具有相同的字段值。我的意思是o1.getField()等于o2.getField()等于o3.getField()。让我们说,o1、o2和o3是相似的

我想要的对每个相似的元素子数组进行一些后置操作(例如。{o1, o2, o3}{o4, o5},.)

很重要:到期数组非常大,缓存(意味着将数组移动到另一个集合或复制其中的一部分)是不可接受的!

问题:,最优雅的方法是什么?

P.S. --我不需要对整个数组进行除法,只需要做一个postAction。我可以得到第一个{o1, o2, o3},制造postAction,而不是第二个,等等……

EN

回答 4

Stack Overflow用户

发布于 2014-05-19 16:10:43

我首先要挑战“数组不能复制”的前提。如果使用System.arrayCopy(),数组复制是非常快的!

下面是我编写的一个小示例程序,它创建、填充和复制一个包含100,000,000元素的数组。

代码语言:javascript
运行
复制
public static void main(final String[] args) {

    final Stopwatch stopwatch = new Stopwatch().start();
    final String[] arr = new String[100_000_000];
    Arrays.fill(arr, "foo");

    final String[] arr2 = new String[arr.length];
    System.arraycopy(arr, 0, arr2, 0, arr.length);
    stopwatch.stop();
    System.out.println(stopwatch.elapsed(MILLISECONDS));

}

在我没有印象的机器上,这需要683毫秒。

  1. 考虑到代码可能运行在比我的机器快得多的机器上,这是不可接受的吗?
  2. 还是您的数组显着地大于100000000元素?

如果这两个都不是“是”,我会使用一些复制解决方案。

票数 1
EN

Stack Overflow用户

发布于 2014-05-19 16:22:28

我假设您正在处理T类型的对象,并且有一个方法isSimilar(T o1, T o2)。我还假设您有一个类Processor<T>,它有一个方法postAction(Iterator<T> i) (可以适应postAction(Iterable<T> i))。

然后我会沿着这些路线走下去。这只是一个方向,不幸的是,我没有任何东西可以测试甚至编译。

代码语言:javascript
运行
复制
public <T>  void process(T[] array, Processor<T> p) {
  for (int i=0, j=1; i<array.length && j<array.length; i=j, j++) {
    while (j<array.length && isSimilar(array[i], array[j])) {
      j++;
    }
    ArrayIterator<T> ai = new ArrayIterator<T>(array, i, j-1);
    p.postAction(ai);
  }
}

class ArrayIterator<T> implements Iterator<T> {
  T[] array;
  int current;
  int end;

  public ArrayIterator(T[] a, int s, int e) {
    array = a;
    current = s;
    end = e;
  }

  public boolean hasNext() {
    return current <= end;
  }

  public T next() {
    return array[current++];
  }
}

如果postAction接受一个List或其他强制的集合,您可以创建这样一个由数组备份的集合,比如Arrays.asList(),但是它将是更多的锅炉板代码。如果postAction需要一个数组,我认为你必须复制.

票数 1
EN

Stack Overflow用户

发布于 2014-05-19 16:53:15

我们有这门课

代码语言:javascript
运行
复制
public static class MisteriousItem {

    public int oddlyFamiliarValue;

    public MisteriousItem(int oddlyFamiliarValue) {
        this.oddlyFamiliarValue = oddlyFamiliarValue;
    }

}

我们用它来放置数组:

代码语言:javascript
运行
复制
    Random rand = new Random();
    MisteriousItem[] magicBox = new MisteriousItem[1_000];
    for (int i = 0; i < magicBox.length; i++) {
        magicBox[i] = new MisteriousItem(rand.nextInt(3));
    }

然后我们准备了很少的价值

代码语言:javascript
运行
复制
    List<Entry<Integer, String>> something;
    something = new ArrayList<>();

    MisteriousItem x = magicBox[0];
    StringBuilder sb = new StringBuilder("{");
    sb.append(x.oddlyFamiliarValue);
    int id = 0;

我知道你说过没有副本,但这不是一种超自然的东西,只是和熟悉的物体有关而已

现在我们迭代

代码语言:javascript
运行
复制
    for (int i = 1; i < magicBox.length; i++) {
        MisteriousItem mi = magicBox[i];
        if (mi.oddlyFamiliarValue == x.oddlyFamiliarValue) {
            sb.append(",");
            sb.append(id++);
        } else {
            sb.append("}");
            something.add(new Entry<>(x.oddlyFamiliarValue, sb.toString()));
            x = mi;
            sb = new StringBuilder("{");
            sb.append(id++);
        }
    }

如您所见,我们接受第一个对象并开始处理,然后从第二个项开始对整个数组进行迭代,在执行任何操作之前,我们将检查它是否类似于以前的对象。然后,我们对比较的结果采取相应的行动。如果你正在寻找一些更优雅的方式,留下评论,说什么应该是不同的。

编辑

也许这是你想要的更多

代码语言:javascript
运行
复制
    int end=0;
    int start= 1;
    MisteriousItem x = magicBox[0];
    for (int i = 1; i < magicBox.length; i++) {
        MisteriousItem mi = magicBox[i];
        if (mi.oddlyFamiliarValue == x.oddlyFamiliarValue) {
            end++;
        } else {
            process(magicBox,start,end);
            //process lost starting from start(inclusive) to end(exclusive)
            start=i;
        }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23742058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档