views:

242

answers:

6

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? Is there seriously no quick way to just say {insert contents of filename.txt here}?

+1  A: 

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 and how you want to update it is the key to selecting the correct way.

Esko
Thanks. My needs are really basic. I just need a way that works and that is easy. I only code for myself.
+10  A: 

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
Ah! I see. Thank you!
John R - be sure to mark the answer as accepted - always a good idea to give credit to the folks who take time to respond...
Kevin Day
+7  A: 

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.

Edit: 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.

Michael Borgwardt
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.
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
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.
hah! I guess I could have just said 2^32 instead.
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
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.
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
+1  A: 

No, there is no #include facility in Java. The pre-processor 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 contianing 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.

Thorbjørn Ravn Andersen
64k! wha?! Perhaps the data in an array does not get converted to byte code?
Frankly I'm not sure. I know, however, that the Jasper compiler in Tomcat (which compiles JSP's to servlets) do al kinds of tricks to avoid hitting the boundary. You may want to look at it to see exactly what it does.
Thorbjørn Ravn Andersen
It's 64K per method, not per class. And I'm pretty sure it includes data.
Michael Borgwardt
A: 

It is a deliberate design decision in the Java platform to not pre-process .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 C-style macro hell.

David Crawshaw
Thanks! Everyone seems to be using Java these days. At this point I still prefer the C-style macro hell.
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
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
+1  A: 

Please read Michael Borgwardt answer first, its like all i wanted to say anyhow.

If you need some primes, you can just calculate them on fly:

/** Sieve of Eratosthenes. Return primes <= 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 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]);
}
Margus
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.
That second bit you posted is handy. I'm keeping a copy of that for future reference.
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