1

When logically something seems as if it would be dead simple, then it turns out to be completely convoluted.

I have not used Java much, so please forgive my ignorance. Here is what I am trying to do:

I have a nice clean algorithm in one .java file, and I want to feed it from an initialized array. The array contains over 40,000 elements, so I want it in a separate file all by itself. How do I do this? Isn't there a quick way to just say {insert contents of filename.txt here}?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

6 Answers6

10

File1.java:

class File1 {
    static int[] bigArray = {1,2,3};
}

File2.java:

class File2 {
    static int main(String[] args) {
        doSomeThingWith(File1.bigArray);
    }
}

You may also use static import to be able to use bigArray without prepending File1..

sepp2k
  • 363,768
  • 54
  • 674
  • 675
7

The basic units of code in Java are classes, not files. Importing files simply makes no sense; it's the wrong level of abstraction. Stop thinking about files; think about code in different classes and how you can call that code. What file the class is defined in (and it doesn't have to be a file at all!) does not matter.

BTW, with 40,000 elements, you may run into limitations on the size of a method if you define them directly in code. It would be better to put the data into a text file and parse that. That way, you also don't have to recompile anything when you change the data.

An alternative to writing a parser for the file would be to calculate the data once, put it into an appropriate Java data structure (array, List, Map, whatever) and then serialize that into a file using ObjectOutputStream. Note that this will cause problems if the data is stored in classes that later change their signature.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • Interesting. It's like the antitheses to the *nix philosophy. The array is ~140K. Does that break the bank? It's a list of prime number gaps from 1 to 550,000 so hopefully it will never change. –  Sep 13 '09 at 10:38
  • The size limit on methods is 64K, which includes instructions, so yes, that's too big. You could split it over several methods, I guess, but it's still ugly. Teh data may not change, but you may still want to extend it. – Michael Borgwardt Sep 13 '09 at 11:13
  • I like the serialization idea, but it won't work in this application. The starting point in the array depends on the number the user wants to factor, then from there the array can be traversed in either direction depending on the number, then it is continually traversed in both directions (the dataset is symmetrical so I threw away half of it) until factors are found. The serialized file could be sqrt(2^64) in size. I got the previous data set below 100k, but for my Java version I made a new dataset without using the number 17. Now it is 6k. –  Sep 13 '09 at 16:37
  • I don't really understand why you think serialization wouldn't work. You're creating the data structure in memory - what could be problematic about writing that exact data structure to disk? – Michael Borgwardt Sep 13 '09 at 17:28
  • My thinking was that 1) the serialization is custom for every program run, 2) the serialization is very large, and 3) disk caching is slow. However I think I misunderstood what you really meant. I'm now thinking you are talking about jumping around in the file as if it were the array instead of reading it in a strictly start-to-finish fashion. –  Sep 13 '09 at 18:36
  • No, I'm talking about reading the entire file into memory in one go (once for each program run) - which would have the same end result as your original plan of intializing it through code, and probably be somewhat faster. – Michael Borgwardt Sep 13 '09 at 21:19
1

Make the algorithm method static. That way you can call it by Object whateverItReturns = NameOfClass.nameOfStaticMethod(args);

Content import can generally be done in multiple ways, depending on exactly what kind of content you want to export. How you want to update it is the key to selecting the correct way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Esko
  • 29,022
  • 11
  • 55
  • 82
  • Thanks. My needs are really basic. I just need a way that works and that is easy. I only code for myself. –  Sep 13 '09 at 11:00
1

No, there isn't any #include facility in Java. The preprocessor known from the C world was not included, which—after a while—turns out to make more robust programs (in my opinion).

You need to create a new class containing what you want, and then refer to it. Java 6 allows for static imports which makes this almost transparent.

Note, that you may risk reaching the maximum byte code size of a single class. I believe it is 64 KB.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
1

Please read Michael Borgwardt's answer first. It’s like all I wanted to say anyhow.

If you need some prime numbers, you can just calculate them on the fly:

/** Sieve of Eratosthenes. Return prime numbers <= max */
static Integer[] getSoE(int max) {
    if (max < 1)
        return new Integer[0];

    BitSet sieve = new BitSet(max / 2);
    ArrayList<Integer> list = new ArrayList<Integer>();
    if (max > 1)
        list.add(2);
    if (max > 2)
        list.add(3);

    for (int i = 5, f = 1; i <= max; i += 3 - f, f = -f)
        if (sieve.get(i >> 1) == false) {
            for (int add, j = i + (add = i << 1); j < max; j += add)
                sieve.set(j >> 1, true);
            list.add(i);
        }

    return list.toArray(new Integer[0]);
}

Assuming you want to read them in from a file:

static Integer[] getPrimeFromFile(String Filename) throws FileNotFoundException {
    ArrayList<Integer> list = new ArrayList<Integer>();

    Scanner sc = new Scanner(new File(Filename));
    while (sc.hasNext())
        list.add(sc.nextInt());
    sc.close();

    return list.toArray(new Integer[0]);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Margus
  • 19,694
  • 14
  • 55
  • 103
  • Thanks. I don't need primes, I actually need the composites between them created by the primes through 17. I'm using the array to speed up a general purpose factorization algorithm that I thought up this morning. Calculating on the fly would slow it down. –  Sep 13 '09 at 11:09
  • That second bit you posted is handy. I'm keeping a copy of that for future reference. –  Sep 13 '09 at 11:12
  • Depending on size of max, getSoE execution times are on my 3 year old laptop: 100k (0.015s), 1m (0.077s), 10m (0.933s). If you are NOT solving Euler problems (spoiler alert), you can take a look at my blog, http://margusmartseppcode.blogspot.com/ (probably not indexed by GoogleBot yet). Solutions 3 and 47 are similar to, what you are trying to do. – Margus Sep 13 '09 at 16:09
0

It is a deliberate design decision in the Java platform to not preprocess .java files. This keeps things simple, and simple is what Java is all about.

As others have suggested, use a static import. Sometimes it feels limiting, but it is wonderful not having to debug a C-style macro hell.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Crawshaw
  • 10,427
  • 6
  • 37
  • 39
  • Thanks! Everyone seems to be using Java these days. At this point I still prefer the C-style macro hell. –  Sep 13 '09 at 10:51
  • The full blown macro system allows for redefining things "out of scope". The Java approach basically say - here is the source, everything in HERE is defined in _this_ class. What is called in other classes is defined THERE - you do not have to look all include files through to get the full definition. Helps maintainers a lot – Thorbjørn Ravn Andersen Sep 13 '09 at 11:07
  • 1
    However, this locality of definition breaks when you include inheritance and overwritten methods. And disappears completely with stuff like AOP and metaprogramming that's included in more "modern" JVm languages. – Michael Borgwardt Sep 13 '09 at 11:20