static initialization of arrays  
Author Message
Johan





PostPosted: 2007-10-16 6:34:00 Top

java-programmer, static initialization of arrays Hi guys,

I started to write some Java today, see the code below. What I want to
do is produce a static array V from several static arrays A, B, ...,
but I don't want V to have any duplicate elements. I was wondering if
there is a better way of coding this up? Also, is there a way to
guarantee that arrays A, B, ... are constructed before S and V without
relying on the order in which they are declared?

Thanks,

Johan

-----------------------------------------

import java.util.*;

class StringSet extends TreeSet<String>
{
public void addAll( String[] strings )
{
for (String s: strings )
{
add( s );
}
}
};

class Main
{
private static final String[] A = { "A1", "A2", "B1" };
private static final String[] B = { "B1", "B2" };
...

private static final StringSet S =
new StringSet ()
{
{
addAll( A );
addAll( B );
...
}
};

private static final String[] V = S.toArray(new String[S.size()]);

...
}

 
ram





PostPosted: 2007-10-16 7:47:00 Top

java-programmer >> static initialization of arrays Johan <email***@***.com> writes:
>produce a static array V from several static arrays A, B, ...,
>but I don't want V to have any duplicate elements.

public class Main
{
public static void main( final java.lang.String[] args )
{
final java.lang.String[] a = { "A1", "A2", "B1" };
final java.lang.String[] b = { "B1", "B2" };

final java.util.Set<java.lang.String> set =
new java.util.HashSet<java.lang.String>();

set.addAll( java.util.Arrays.asList( a ));
set.addAll( java.util.Arrays.asList( b ));

final java.lang.String[] c = set.toArray( a );

java.lang.System.out.println
( java.util.Arrays.toString( c )); }}

[A2, A1, B2, B1]

 
ram





PostPosted: 2007-10-16 9:46:00 Top

java-programmer >> static initialization of arrays email***@***.com (Stefan Ram) writes:
>final java.util.Set<java.lang.String> set =
>new java.util.HashSet<java.lang.String>();

When answering, I actually had not yet read
the question to the end, so that my answer
might not address all questions of the OP.

I only answered to how to merge arrays
removing duplicates - not being aware that
the OP already used java.util.Set.

 
 
Patricia Shanahan





PostPosted: 2007-10-16 9:53:00 Top

java-programmer >> static initialization of arrays Johan wrote:
> Hi guys,

guys?

>
> I started to write some Java today, see the code below. What I want to
> do is produce a static array V from several static arrays A, B, ...,
> but I don't want V to have any duplicate elements. I was wondering if
> there is a better way of coding this up? Also, is there a way to
> guarantee that arrays A, B, ... are constructed before S and V without
> relying on the order in which they are declared?

Have you considered using a static initializer block?

They are handy when a static variable needs initializing and the
initialization is too complicated to go in the variable declaration.

If you put it after the declarations of A, B, ... there will be no
forward reference problems.

Patricia
 
 
Daniel Pitts





PostPosted: 2007-10-16 12:14:00 Top

java-programmer >> static initialization of arrays On Oct 15, 3:33 pm, Johan <email***@***.com> wrote:
> Hi guys,
>
> I started to write some Java today, see the code below. What I want to
> do is produce a static array V from several static arrays A, B, ...,
> but I don't want V to have any duplicate elements. I was wondering if
> there is a better way of coding this up?
[snip]
>
> import java.util.*;
>
> class StringSet extends TreeSet<String>
> {
> public void addAll( String[] strings )
> {
> for (String s: strings )
> {
> add( s );
> }
> }
>
> };
No need for a special StringSet class...
>
> class Main
> {
> private static final String[] A = { "A1", "A2", "B1" };
> private static final String[] B = { "B1", "B2" };
> ...
>
> private static final StringSet S =
> new StringSet ()
> {
> {
> addAll( A );
> addAll( B );
> ...
> }
> };
>
> private static final String[] V = S.toArray(new String[S.size()]);
>
> ...
>
> }

You really should use List instead of String[], but I'll show you both
ways:

import java.util.*;

public class Main {
public static final String[] A = { "A1", "A2", "B1" };
public static final String[] B = { "B1", "B2" };
public static final String[] V;
static {
Set<String> stringSet = new
LinkedHashSet<String>(Arrays.asList(A));
stringSet.addAll(Arrays.asList(B));
V = stringSet.toArray(new String[stringSet.size()]);
}
}

The problem with that approach, is that A and B and V are still
mutable!
V[0] = "B1" will have an effect you don't want.

import java.util.*;

public class MainWithCollection {
public static final List<String> A =
Collections.unmodifiableList(Arrays.asList("A1", "A2", "B1"));
public static final List<String> B =
Collections.unmodifiableList(Arrays.asList("A1", "B1", "B2"));
public static final List<String> V;
static {
Set<String> stringSet = new LinkedHashSet<String>(A);
stringSet.addAll(B);
ArrayList<String> stringList = new ArrayList<String>(stringSet);
stringList.trimToSize();
V = Collections.unmodifiableList(stringList);
}
}

> Also, is there a way to
> guarantee that arrays A, B, ... are constructed before S and V without
> relying on the order in which they are declared?
If they are in the same class, then you have to declare them in the
order you expect them to be initialized. The compiler won't let you
refer to them before they are. You can use a static initializer (such
as I did) to explicitly initialize them in a particular order.

Now, if you have many arrays/lists to add together (more than just A
and B), you might consider two things: One, loading this data from an
external source (data file, for instance), and at the very least, use
a for-loop to iterate over them:

public class Main {
public static final Object[] a1 = {1, 2, 3};
public static final Object[] a2 = {1, 2, 3};
public static final Object[] a3 = {1, 2, 3};
public static final Object[] a4 = {1, 2, 3};

static {
for (Object[] arr : new Object[][] {a1, a2, a3, a4}) {
}
}
}

Or similarly with the List version.

The more I think about this, the more I think you should separate out
these strings into an external file, and not have them be public nor
static. What is it that you're trying to achieve?

 
 
Johan





PostPosted: 2007-10-16 15:24:00 Top

java-programmer >> static initialization of arrays Thanks for all the replies, people. What I'm trying to achieve is
illustrated by the following 'code':

class Base
{
static final String[] A = {1, 2, 3};
static final String[] B = {3, 4, 5};
static final String[] C = {...};
...
};

class Derived1
{
static final String[] V = A union B;
}

class Derived2
{
static final String[] V = A union B union C;
}

So I'm really trying to write a collection of static final arrays (or
lists) in my baseclass and then combine them in various ways in
different derived classes. Because A, B etc are in a different class,
I am worried about the initialisation problem. I know that base
objects are constructed before derived objects, bur I'm not so sure if
this is true for static objects.

The reason that I used arrays rather than lists is that I thought they
would more efficient (otherwise you would have to constuct a linked
list from an array and then use that to populate the set). I know this
is not an issue, as it happens during static initialization, but it's
a force of habit :-)

Thanks,

Johan

On Oct 16, 5:13 am, Daniel Pitts <email***@***.com> wrote:
> On Oct 15, 3:33 pm, Johan <email***@***.com> wrote:
>
>
>
> > Hi guys,
>
> > I started to write some Java today, see the code below. What I want to
> > do is produce a static array V from several static arrays A, B, ...,
> > but I don't want V to have any duplicate elements. I was wondering if
> > there is a better way of coding this up?
> [snip]
>
> > import java.util.*;
>
> > class StringSet extends TreeSet<String>
> > {
> > public void addAll( String[] strings )
> > {
> > for (String s: strings )
> > {
> > add( s );
> > }
> > }
>
> > };
>
> No need for a special StringSet class...
>
>
>
>
>
>
>
> > class Main
> > {
> > private static final String[] A = { "A1", "A2", "B1" };
> > private static final String[] B = { "B1", "B2" };
> > ...
>
> > private static final StringSet S =
> > new StringSet ()
> > {
> > {
> > addAll( A );
> > addAll( B );
> > ...
> > }
> > };
>
> > private static final String[] V = S.toArray(new String[S.size()]);
>
> > ...
>
> > }
>
> You really should use List instead of String[], but I'll show you both
> ways:
>
> import java.util.*;
>
> public class Main {
> public static final String[] A = { "A1", "A2", "B1" };
> public static final String[] B = { "B1", "B2" };
> public static final String[] V;
> static {
> Set<String> stringSet = new
> LinkedHashSet<String>(Arrays.asList(A));
> stringSet.addAll(Arrays.asList(B));
> V = stringSet.toArray(new String[stringSet.size()]);
> }
>
> }
>
> The problem with that approach, is that A and B and V are still
> mutable!
> V[0] = "B1" will have an effect you don't want.
>
> import java.util.*;
>
> public class MainWithCollection {
> public static final List<String> A =
> Collections.unmodifiableList(Arrays.asList("A1", "A2", "B1"));
> public static final List<String> B =
> Collections.unmodifiableList(Arrays.asList("A1", "B1", "B2"));
> public static final List<String> V;
> static {
> Set<String> stringSet = new LinkedHashSet<String>(A);
> stringSet.addAll(B);
> ArrayList<String> stringList = new ArrayList<String>(stringSet);
> stringList.trimToSize();
> V = Collections.unmodifiableList(stringList);
> }
>
> }
> > Also, is there a way to
> > guarantee that arrays A, B, ... are constructed before S and V without
> > relying on the order in which they are declared?
>
> If they are in the same class, then you have to declare them in the
> order you expect them to be initialized. The compiler won't let you
> refer to them before they are. You can use a static initializer (such
> as I did) to explicitly initialize them in a particular order.
>
> Now, if you have many arrays/lists to add together (more than just A
> and B), you might consider two things: One, loading this data from an
> external source (data file, for instance), and at the very least, use
> a for-loop to iterate over them:
>
> public class Main {
> public static final Object[] a1 = {1, 2, 3};
> public static final Object[] a2 = {1, 2, 3};
> public static final Object[] a3 = {1, 2, 3};
> public static final Object[] a4 = {1, 2, 3};
>
> static {
> for (Object[] arr : new Object[][] {a1, a2, a3, a4}) {
> }
> }
>
> }
>
> Or similarly with the List version.
>
> The more I think about this, the more I think you should separate out
> these strings into an external file, and not have them be public nor
> static. What is it that you're trying to achieve?- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -


 
 
Lew





PostPosted: 2007-10-16 20:40:00 Top

java-programmer >> static initialization of arrays Johan wrote:
> Thanks for all the replies, people.

Please, please, please, please, please do not top-post.

> The reason that I used arrays rather than lists is that I thought they
> would more efficient (otherwise you would have to constuct a linked
> list from an array and then use that to populate the set). I know this
> is not an issue, as it happens during static initialization, but it's
> a force of habit :-)

Be aware that not all Lists are LinkedLists. And what does "efficient" mean
to you - a week of figuring out how to code something to save a millisecond
that will be optimized away by the HotSpotter anyway?

Since you're looking into using Collections to implement your features anyway,
i.e., using a Set to prevent duplicate entries, you might consider going
Collection all the way and not using explicit arrays.

This also lets you use generics for type safety.

--
Lew
 
 
Daniel Pitts





PostPosted: 2007-10-17 8:18:00 Top

java-programmer >> static initialization of arrays On Oct 16, 12:23 am, Johan <email***@***.com> wrote:
> Thanks for all the replies, people. What I'm trying to achieve is
> illustrated by the following 'code':
>
[snip]

> So I'm really trying to write a collection of static final arrays (or
> lists) in my baseclass and then combine them in various ways in
> different derived classes. Because A, B etc are in a different class,
> I am worried about the initialisation problem. I know that base
> objects are constructed before derived objects, bur I'm not so sure if
> this is true for static objects.
>
> The reason that I used arrays rather than lists is that I thought they
> would more efficient (otherwise you would have to constuct a linked
> list from an array and then use that to populate the set). I know this
> is not an issue, as it happens during static initialization, but it's
> a force of habit :-)
>
> Thanks,


*Why* are you doing this? How will it improve your end-users
experience?

 
 
Roedy Green





PostPosted: 2007-10-17 9:19:00 Top

java-programmer >> static initialization of arrays On Mon, 15 Oct 2007 15:33:56 -0700, Johan <email***@***.com>
wrote, quoted or indirectly quoted someone who said :

> Also, is there a way to
>guarantee that arrays A, B, ... are constructed before S and V without
>relying on the order in which they are declared?

use static init code. Inside the static init, the inits must be done
in order.

see http://mindprod.com/jgloss/array.html
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
 
Johan





PostPosted: 2007-10-18 4:25:00 Top

java-programmer >> static initialization of arrays On 17 Oct, 01:18, Daniel Pitts <email***@***.com> wrote:
> On Oct 16, 12:23 am, Johan <email***@***.com> wrote:> Thanks for all the replies, people. What I'm trying to achieve is
> > illustrated by the following 'code':
>
> [snip]
>
> > So I'm really trying to write a collection of static final arrays (or
> > lists) in my baseclass and then combine them in various ways in
> > different derived classes. Because A, B etc are in a different class,
> > I am worried about the initialisation problem. I know that base
> > objects are constructed before derived objects, bur I'm not so sure if
> > this is true for static objects.
>
> > The reason that I used arrays rather than lists is that I thought they
> > would more efficient (otherwise you would have to constuct a linked
> > list from an array and then use that to populate the set). I know this
> > is not an issue, as it happens during static initialization, but it's
> > a force of habit :-)
>
> > Thanks,
>
> *Why* are you doing this? How will it improve your end-users
> experience?

My sub-classes send queries to a database. Some of these queries are
specific to a sub-type, other queries are common to several sub-types.
I grouped the queries into sets by function and by storing the these
sets in the base class, sub types can use and combine them as
necessary. This makes it easier to add new subtypes in the future. I
hope this is clear so far.

With regards to using arrays as opposed to containers for this
purpose, I agree that it is better to use containers as performance is
not an issue. I only just started writing Java - I am used to
developing C++ applications where performance *is* an issue and where
converting between STL containers is often not appropriate.

Thanks,

Johan

 
 
Daniel Pitts





PostPosted: 2007-10-19 23:45:00 Top

java-programmer >> static initialization of arrays On Oct 17, 1:25 pm, Johan <email***@***.com> wrote:
> On 17 Oct, 01:18, Daniel Pitts <email***@***.com> wrote:
>
>
>
> > On Oct 16, 12:23 am, Johan <email***@***.com> wrote:> Thanks for all the replies, people. What I'm trying to achieve is
> > > illustrated by the following 'code':
>
> > [snip]
>
> > > So I'm really trying to write a collection of static final arrays (or
> > > lists) in my baseclass and then combine them in various ways in
> > > different derived classes. Because A, B etc are in a different class,
> > > I am worried about the initialisation problem. I know that base
> > > objects are constructed before derived objects, bur I'm not so sure if
> > > this is true for static objects.
>
> > > The reason that I used arrays rather than lists is that I thought they
> > > would more efficient (otherwise you would have to constuct a linked
> > > list from an array and then use that to populate the set). I know this
> > > is not an issue, as it happens during static initialization, but it's
> > > a force of habit :-)
>
> > > Thanks,
>
> > *Why* are you doing this? How will it improve your end-users
> > experience?
>
> My sub-classes send queries to a database. Some of these queries are
> specific to a sub-type, other queries are common to several sub-types.
> I grouped the queries into sets by function and by storing the these
> sets in the base class, sub types can use and combine them as
> necessary. This makes it easier to add new subtypes in the future. I
> hope this is clear so far.
>
> With regards to using arrays as opposed to containers for this
> purpose, I agree that it is better to use containers as performance is
> not an issue. I only just started writing Java - I am used to
> developing C++ applications where performance *is* an issue and where
> converting between STL containers is often not appropriate.
>
> Thanks,
>
> Johan

I'm still thinking that it might be useful for you to externalize all
of this data. At least consider it.