【问题标题】:Fill arrays with ranges of numbers用数字范围填充数组
【发布时间】:2010-08-02 11:45:45
【问题描述】:

是否有任何语法/包允许使用数字范围快速填充 java 数组,例如 perl?

例如

int[] arr = new int[1000];
arr=(1..500,301..400,1001..1400); // returns [1,2,3,4,...,500,301,302,...,400,1001,1002,...1400]

另外,它是一个包,允许在上述数字列表中获取第 n 个数字,而无需实际创建数组(可能很大)?

例如

BunchOfRangesType bort = new BunchOfRangesType("1..500","301..400","1001..1400");
bort.get(0); // return 1
bort.get(500); // return 301
bort.get(501); // return 302

实现起来并不太难,但我想它可能很常见,所以可能已经完成了。

【问题讨论】:

  • 或者只使用 Groovy ;-) def arr = (1..500)+(301..400)+(1001..1400)

标签: java arrays


【解决方案1】:

对于那些仍在寻找解决方案的人:

在 Java 8 或更高版本中,可以使用 Streams 轻松解决此问题,无需任何循环或其他库。

int[] range = IntStream.rangeClosed(1, 10).toArray();

这将产生一个整数从 1 到 10 的数组。

下面是产生相同结果的更通用的解决方案。这可以通过修改一元运算符来产生任何序列。

int[] range = IntStream.iterate(1, n -> n + 1).limit(10).toArray();

【讨论】:

  • 在 JDK-9 中,最后一个变体可以是 int[] range = IntStream.iterate(1, n -> n <= 10, n -> n + 1).toArray();
  • 对于那些(像我一样)想要将结果范围放在列表中的人,您可以使用IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList())(感谢stackoverflow.com/questions/23674624/…
  • IntStream 适用于 API LEVEL 24+ (Android Studio)。对于低于 24 的 API LEVEL,我们有什么这么简单的解决方案?
【解决方案2】:

dollar

// build the List 10, 11, 12, 13, 14
List<Integer> list2 = $(10, 15).toList();

行家:

<dependency>
        <groupId>org.bitbucket.dollar</groupId>
        <artifactId>dollar</artifactId>
        <version>1.0-beta3</version>
</dependency>

【讨论】:

  • 我也找不到这样的东西。仅当您自己定义 $ 方法时,这在 Java 中才有效。
  • 经过进一步审查,似乎“dollar”是一个将 $ 方法定义为 Dollar 类的静态方法的库。由于链接失效,几乎不可能真正找到它的代码。所以这个答案是毫无用处的。完整的 java 语法需要将其称为 Dollar.$(10, 15).toList().
  • @Erick,是的,$ 是一种方法。 '链接失效' 是什么意思?该库的源代码也可用。
  • @Erick - 如果你不是 import static com.humaorie.dollar.Dollar.*.
  • 链接正常。我的意思是,如果我点击答案中的链接,我会转到该页面。
【解决方案3】:

现有数组的另一种有用但不广为人知的 Java 8 解决方案:

int[] array = new int[10];
Arrays.setAll(array, i -> i + 1);

【讨论】:

    【解决方案4】:

    至于第一个问题,是否可以用范围的值填充数组:实际上可以通过RangeDiscreteDomainContiguousSetInts的组合来实现来自Guava

    int[] array = Ints.toArray(
        ContiguousSet.create(Range.closed(1, 500), DiscreteDomain.integers()));
    

    而且,不完全是问题第二部分中提到的内容,但可以使用离散域范围内的元素创建一个集合:

    Set<Integer> numbersFrom1To500 = 
        ContiguousSet.create(Range.closed(1, 500), DiscreteDomain.integers());
    

    生成的Set 将不包含物理上的指定元素,仅在逻辑上包含(因此它的内存占用会很小),但可以迭代(因为它是Set):

    for (Integer integer : numbersFrom1To500) {
        System.out.println(integer);
    }
    

    【讨论】:

    • 很好.. 不知道。
    【解决方案5】:

    不像 True Soft 的回答那样干净,但您可以使用 Google Guava 达到相同的效果:

    public class Test {
    
        public static void main(String[] args) {
            //one liner
            int[] array = toArray(newLinkedList(concat(range(1, 10), range(500, 1000))));
    
            //more readable
            Iterable<Integer> values = concat(range(1, 10), range(500, 1000));
            List<Integer> list = newLinkedList(values);
            int[] array = toArray(list);
    
        }
    
        public static List<Integer> range(int min, int max) {
            List<Integer> list = newLinkedList();
            for (int i = min; i <= max; i++) {
                list.add(i);
            }
    
            return list;
        }
    
    }
    

    请注意,您需要一些静态导入才能使其正常工作。

    【讨论】:

    • 即使更冗长,也比美元方法要清楚得多。
    • 我认为静态导入不是很干净。我更喜欢自定义实现而不是这样做。
    • @Erick “我认为静态导入不是很干净。”您当然可以使用完全限定的方法名称,但是使用静态导入确实可以使代码不那么冗长。
    • 冗长可以提高可读性,这是所希望的。调用静态方法时,我总是引用类名。我想让下一个程序员尽可能容易理解。我看不出使代码不那么冗长或紧凑到足以容纳一行的好处。这些东西对提高性能没有任何帮助,只会混淆代码。
    • “请注意,您需要一些静态导入才能使其工作”,将它们包含在您的代码中会很有帮助。 range(...) 可以在 com.google.common.collect.Range toArray(Range) 可以在 com.google.common.collect.Iterables newLinkedList(..) 可以在 com. google.common.collect.Lists
    【解决方案6】:
        List<Integer> arrayOfRange  = new ArrayList<Integer>();
        int[] range = IntStream.iterate(1, n -> {arrayOfRange.add(n);return n + 1;}).limit(10).toArray();
    

    // 如果你想要 Integer,除了 craig 的回答 第二种方法

    List<Integer> list = IntStream.of(range).boxed().collect(Collectors.toList());
    

    【讨论】:

      【解决方案7】:
       public static int[] getRangeArray(int start, int end){
              final int[] rangeArray = new int[end-start + 1];
                  for(int i = 0; i < rangeArray.length; i++){
                      rangeArray[i] = start + i;
                }
             return rangeArray; // It includes start and end values as well, pls adjust according to your need
        }
      

      【讨论】:

        猜你喜欢
        • 2016-07-01
        • 2018-08-03
        • 1970-01-01
        • 2021-09-26
        • 1970-01-01
        • 2016-06-28
        • 1970-01-01
        • 2014-09-11
        • 1970-01-01
        相关资源
        最近更新 更多