HashMap.put error in Xcode

C

Composer

I'm using Apple's Xcode 1.1 and have had no big problem with it until
now. I've created a HashMap and used the put() method to insert a
BitSet into it, but cannot get the compiler to like it. A paraphrase
of my code:

import java.util.*;
HashMap hm = new HashMap(72);
BitSet bs = new BitSet(12);
hm.put(bs.hashCode(), bs);

The error message from Xcode is:

cannot resolve symbol : method put(int,java.util.BitSet)

If I change the BitSet to a String, or change the HashMap to a
Hashtable, I get the same error. I don't understand this, because the
put() method takes an integer and an Object, and I believe that's what
I'm providing it. Is it possible that Xcode 1.1 is doing something
wrong? Thanks.
 
M

Mike Schilling

Composer said:
I'm using Apple's Xcode 1.1 and have had no big problem with it until
now. I've created a HashMap and used the put() method to insert a
BitSet into it, but cannot get the compiler to like it. A paraphrase
of my code:

import java.util.*;
HashMap hm = new HashMap(72);
BitSet bs = new BitSet(12);
hm.put(bs.hashCode(), bs);

The error message from Xcode is:

cannot resolve symbol : method put(int,java.util.BitSet)

If I change the BitSet to a String, or change the HashMap to a
Hashtable, I get the same error. I don't understand this, because the
put() method takes an integer and an Object, and I believe that's what
I'm providing it. Is it possible that Xcode 1.1 is doing something
wrong? Thanks.

HashMap requires an Object as the key. This will compile if you code

hm.put(new Integer(bs.hashCode()), bs);

But it seems unlikely that hashCode() will give you a useful key. It's not
something you're likely to know if you don't already have the object handy,
nor is it guaranteed to be unique. What are you trying to do?
 
T

Tom Hawtin

Composer said:
import java.util.*;
HashMap hm = new HashMap(72);
BitSet bs = new BitSet(12);
hm.put(bs.hashCode(), bs);

The error message from Xcode is:

cannot resolve symbol : method put(int,java.util.BitSet)

Firstly, a BitSet (or pretty much any type) will not have a unique hash
code. There can only be 2^32 hash codes, but there are many more
possibilities for BitSet. Would a Set be more appropriate?

Secondly, I suggest you use Java 1.5 (1.6 if you didn't have to put up
with Apple) and generics.

Thirdly, made up initials like 'hm' make the code very difficult to read.

Fourthly, It's much better to least specific types where you don't have
to mention the implementation. In this case, other than construction we
don't need to know you are using HashMap.

Fifthly, importing an entire package is rarely a good idea. It's
difficult to see where the types are coming from.

Anyway:

Assuming 1.4, you are trying to use an int where an Object is expected.
An int is a primitive, which are not Objects. So you need to 'box' the
int into some sort of Object. An Integer will do fine. So (ignoring the
non-uniqueness of hash codes; generics commented out):

import java.util.BitSet;
import java.util.Map;

Map/*<Integer,BitSet>*/ map =
new java.util.HashMap/*<Integer,BitSet>*/(72);
BitSet bits = new BitSet(12);
map.put(new Integer(bits.hashCode()), bits);

Tom Hawtin
 
C

Composer

Humble apologies to all.
I didn't look closely enough at the HashMap.put() documentation. Of
course you're right; it takes two Objects. I had misinterpreted what
my 1999 Sams book said: "Any class that defines a hashCode() method
can be efficiently stored and accessed in a hash table." Since the
hashCode() methods of BitSet and String return an int, I assumed that
an int would be suitable as a key in a HashMap. I was wrong.

(Why do these classes have a hashCode() method, if it doesn't create a
unique key?)

To answer why I was using a HashMap in the first place, I expect the
user to generate a large number of 12-bit BitSets. I want to do 2
things with them: de-duplicate them before adding them to a list,
then draw certain subsets from the list based on certain bits in each
BitSet being on or off. It seemed that a BitSet, with its and() and
or() methods, would support the second objective, and storing the
BitSets in a HashMap would allow easy de-duplication and speedy
searching.

If it's true that the hashCode() method won't reliably give me a
unique key for each BitSet, then I could create my own; maybe a short
(16 bit) number could be created in which the first 12 bits are
significant. But maybe I should abandon the whole idea of hash codes
and keys, and simply put all my BitSets into a Vector, which I would
search manually using the BitSet.equals() method.

Although I've created several small Java applications, I'm not a
professional Java programmer, so if I can continue using a free
environment like Xcode it would be economic. That means, at the
present, that 1.4.2 is my upper limit for Java versions.

Thanks very much for your speedy help.
 
Z

zero

Although I've created several small Java applications, I'm not a
professional Java programmer, so if I can continue using a free
environment like Xcode it would be economic. That means, at the
present, that 1.4.2 is my upper limit for Java versions.

All you need to develop java applications is the SDK, which is free, and a
text editor. Even if you want an integrated environment, there are plenty
of choices besides Xcode, with eclipse probably being the most popular.

Anyway, unless you need to support Panther, you can switch to 1.5.
Unfortunately 1.5 doesn't run under Panther, but Tiger and Leopard are no
problem. I'm not 100% sure Xcode can handle 1.5 (I think it can), but if
it can't you can just switch to a different editor.

Zero
 
P

Patricia Shanahan

Composer said:
Humble apologies to all.
I didn't look closely enough at the HashMap.put() documentation. Of
course you're right; it takes two Objects. I had misinterpreted what
my 1999 Sams book said: "Any class that defines a hashCode() method
can be efficiently stored and accessed in a hash table." Since the
hashCode() methods of BitSet and String return an int, I assumed that
an int would be suitable as a key in a HashMap. I was wrong.

(Why do these classes have a hashCode() method, if it doesn't create a
unique key?)

The point of hash-based data structures is to partition the keys, based
on a hash code, so that only a subset of the keys in the data structure
need to be searched for any given access.
To answer why I was using a HashMap in the first place, I expect the
user to generate a large number of 12-bit BitSets. I want to do 2
things with them: de-duplicate them before adding them to a list,
then draw certain subsets from the list based on certain bits in each
BitSet being on or off. It seemed that a BitSet, with its and() and
or() methods, would support the second objective, and storing the
BitSets in a HashMap would allow easy de-duplication and speedy
searching.

If it's true that the hashCode() method won't reliably give me a
unique key for each BitSet, then I could create my own; maybe a short
(16 bit) number could be created in which the first 12 bits are
significant. But maybe I should abandon the whole idea of hash codes
and keys, and simply put all my BitSets into a Vector, which I would
search manually using the BitSet.equals() method.

I still don't see why you cannot use a HashMap with BitSet keys. It is
VERY unlikely that your BitSet instances all have the same hash code,
and that is what it would take to make a HashMap access as inefficient
as a linear search of a Vector.

Or use a HashSet of BitSet elements.

You could probably do the task more efficiently using short, if you
designed your data structures carefully, but it would be more work.

Patricia
 
T

Tom Hawtin

Composer said:
To answer why I was using a HashMap in the first place, I expect the
user to generate a large number of 12-bit BitSets. I want to do 2
things with them: de-duplicate them before adding them to a list,
then draw certain subsets from the list based on certain bits in each
BitSet being on or off. It seemed that a BitSet, with its and() and
or() methods, would support the second objective, and storing the
BitSets in a HashMap would allow easy de-duplication and speedy
searching.

It seems that a HashSet/*<BitSet>*/ would remove duplicates for you fine.

As for searching, it depends upon your criteria. If it's an exact match,
a HashSet should be fine. If you need ranges, then a TreeSet/*<BitSet>*/
(that is a SortedSet, of NavigableSet in 1.6) with an appropriate
Comparator would be fine. Anything more complicated and you're looking
multiple maps, or scanning the entire set of BitSets.

If you are only dealing with 12-bits, you can easily use an int instead
of a BitSet (there's not much point in using a short, unless you have
large arrays of them). 12-bits only gives you 4096 possibilities, which
would be small on a Vic 20. If you have an int instead of BitSet, and
it's only 12 bits, then you can use the int as an index into a BitSet or
an array. That will give you fast scanning (if you are prepared not to
create BitSets as you scanned).

Tom Hawtin
 
D

Daniel Pitts

Humble apologies to all.
I didn't look closely enough at the HashMap.put() documentation. Of
course you're right; it takes two Objects. I had misinterpreted what
my 1999 Sams book said: "Any class that defines a hashCode() method
can be efficiently stored and accessed in a hash table." Since the
hashCode() methods of BitSet and String return an int, I assumed that
an int would be suitable as a key in a HashMap. I was wrong.
The Key to a hashmap is an actual key, not the hash of the key.
HashMap calls hashCode() on the key in order to partition the keys in
to easy-to-find buckets.
(Why do these classes have a hashCode() method, if it doesn't create a
unique key?)
Like whats been stated alread, hashCode() returns a "hash", which is
*likely* to be different between two objects. This lets you store them
in different locations. Think of it like sorting your clothes by
color. The color is the hash code. You know you want a red shirt, so
you first look for "reds", then you search for "shirt".
To answer why I was using a HashMap in the first place, I expect the
user to generate a large number of 12-bit BitSets. I want to do 2
things with them: de-duplicate them before adding them to a list,
then draw certain subsets from the list based on certain bits in each
BitSet being on or off. It seemed that a BitSet, with its and() and
or() methods, would support the second objective, and storing the
BitSets in a HashMap would allow easy de-duplication and speedy
searching.
A couple of things here. First, BitSets are a bit overkill for 12
bits. I suggest using a simple integer, or at least a custom wrapper
around an int. BitSets contain an array of longs, so you don't gain
any space benefit from using BitSet instead of "int". Although you
might get some clarity, depends on what your doing.

Second, you should use a Set, (not a map) to remove duplicates.
If it's true that the hashCode() method won't reliably give me a
unique key for each BitSet, then I could create my own; maybe a short
(16 bit) number could be created in which the first 12 bits are
significant. But maybe I should abandon the whole idea of hash codes
and keys, and simply put all my BitSets into a Vector, which I would
search manually using the BitSet.equals() method.

Or, put them into an ArrayList, and call List.contains() on them :)
Although I've created several small Java applications, I'm not a
professional Java programmer, so if I can continue using a free
environment like Xcode it would be economic. That means, at the
present, that 1.4.2 is my upper limit for Java versions.

I believe Eclipse is free, although I use IntelliJ IDEA, and it does
cost money. You can install JDK 1.5+ and use any text editor to edit
classes, although a good IDE is definitely worth a bit of money.


Thanks very much for your speedy help.

I hope this does indeed help you.
Good luck,
Daniel.
 
C

Composer

Thanks again to all.

I have thought more clearly now, and abandoned the hash code approach
in favor of putting the BitSets into an ArrayList, and calling
List.contains() on them. This is an easy solution to my de-
duplicating requirement when building the list. Thanks.

When searching the list for sets having specific bits turned on or
off, I have to inspect every set in the ArrayList; there is no "key"
that would have helped this operation. So I really just needed an
Iterator for this requirement.

An int would do the job instead of a BitSet. But I'm still using
BitSet because I have to do other operations on the sets (rotation,
inversion) and I find these easier than bit operations. It's a single-
user, small-scale application, and I don't expect memory to be an
issue.

Thanks again, all.
 
D

Daniel Pitts

Thanks again to all.

I have thought more clearly now, and abandoned the hash code approach
in favor of putting the BitSets into an ArrayList, and calling
List.contains() on them. This is an easy solution to my de-
duplicating requirement when building the list. Thanks.

When searching the list for sets having specific bits turned on or
off, I have to inspect every set in the ArrayList; there is no "key"
that would have helped this operation. So I really just needed an
Iterator for this requirement.

An int would do the job instead of a BitSet. But I'm still using
BitSet because I have to do other operations on the sets (rotation,
inversion) and I find these easier than bit operations. It's a single-
user, small-scale application, and I don't expect memory to be an
issue.

Thanks again, all.

public class BitSetCollection {
List<BitSet> all = new ArrayList<BitSet>();
Map<Integer, List<BitSet>> withBitSet = new HashMap<Integer,
List<BitSet>>();
public void addBitSet(BitSet bs) {
if (all.contains(bs)) {
return;
}
for (int i = 0; i < 12; ++i) {
if (bs.get(i)) {
List<BitSet> sets = withBitSet.get(new Integer(i));
if (sets == null) {
sets = new ArrayList<BitSet>();
withBitSet.put(new Integer(i), sets);
}
sets.add(i);
}
}
}

public List<BitSet> withBitSet(int bit) {
return withBitSet.get(new Integer(i));
}
}

As a starting point :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top