Skip to content

Commit 2a935b0

Browse files
Scott L. BursonScott L. Burson
authored andcommitted
Fix serious bug: deserialized collections all had hash code 0!
Also, remove some useless methods, and minor cleanup.
1 parent 9384373 commit 2a935b0

8 files changed

Lines changed: 56 additions & 84 deletions

File tree

com/ergy/fset/FHashMap.java

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
* these circumstances, the user must be sure that the value objects are acceptable
8888
* to the <code>Comparator</code>, or that they implement <code>Comparable</code>.
8989
*
90-
* <p><code>FHashMap</code> implements {@link java.io.Serializable}; an instance
90+
* <p><code>FHashMap</code> implements {@link Serializable}; an instance
9191
* of it is serializable provided that all keys and values it contains, the
9292
* <code>Comparator</code> it uses if any, and the default value if nonnull, are
9393
* serializable.
@@ -200,14 +200,6 @@ public Map.Entry<Key, Val> arb() {
200200
return (Map.Entry<Key, Val>)arb(tree);
201201
}
202202

203-
public Key firstKey() {
204-
return (Key)firstKey(tree);
205-
}
206-
207-
public Key lastKey() {
208-
return (Key)lastKey(tree);
209-
}
210-
211203
/**
212204
* Returns true iff this map contains an entry with key <code>entry.getKey()</code>,
213205
* with corresponding value <code>entry.getValue()</code>. (Returns false when there
@@ -521,35 +513,6 @@ else if (!(tree instanceof Node)) {
521513
}
522514
}
523515

524-
/*pkg*/ static Object firstKey(Object subtree) {
525-
if (!(subtree instanceof Node)) {
526-
Object[] ary = (Object[])subtree;
527-
return ary[0];
528-
} else {
529-
Node node = (Node)subtree;
530-
if (node.left == null) {
531-
if (node.key instanceof EquivalentMap)
532-
return ((EquivalentMap)node.key).contents.get(0).key;
533-
else return node.key;
534-
} else return firstKey(node.left);
535-
}
536-
}
537-
538-
/*pkg*/ static Object lastKey(Object subtree) {
539-
if (!(subtree instanceof Node)) {
540-
Object[] ary = (Object[])subtree;
541-
return ary[(ary.length >> 1) - 1];
542-
} else {
543-
Node node = (Node)subtree;
544-
if (node.right == null) {
545-
if (node.key instanceof EquivalentMap) {
546-
ArrayList<Entry> al = ((EquivalentMap)node.key).contents;
547-
return al.get(al.size() - 1).key;
548-
} else return node.key;
549-
} else return lastKey(node.right);
550-
}
551-
}
552-
553516
/*pkg*/ static <Key, Val> boolean contains(Object tree, Map.Entry<Key, Val> entry) {
554517
Key key = entry.getKey();
555518
Object val = get(tree, key, hashCode(key));
@@ -2032,6 +1995,7 @@ private void writeObject(ObjectOutputStream strm) throws IOException {
20321995
* Reconstitutes the <code>FHashMap</code> instance from a stream.
20331996
*/
20341997
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
1998+
hash_code = Integer.MIN_VALUE;
20351999
strm.defaultReadObject(); // reads `comp' and `dflt'
20362000
int size = strm.readInt();
20372001
tree = null;

com/ergy/fset/FHashSet.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
*
5151
* <p><code>FHashSet</code> accepts the null element.
5252
*
53-
* <p><code>FHashSet</code> implements {@link java.io.Serializable}; an instance
53+
* <p><code>FHashSet</code> implements {@link Serializable}; an instance
5454
* of it is serializable provided that all elements it contains are serializable.
5555
*
5656
* @author Scott L. Burson
@@ -1627,7 +1627,7 @@ public void remove () {
16271627
* @serialData Emits the internal data of the set, including the size of the set
16281628
* [<code>int</code>]; and the elements in order [<code>Object</code>s].
16291629
*/
1630-
private void writeObject(java.io.ObjectOutputStream strm) throws java.io.IOException {
1630+
private void writeObject(ObjectOutputStream strm) throws IOException {
16311631
strm.defaultWriteObject(); // writes `comp'
16321632
strm.writeInt(size());
16331633
for (Object e : this)
@@ -1637,8 +1637,8 @@ private void writeObject(java.io.ObjectOutputStream strm) throws java.io.IOExcep
16371637
/**
16381638
* Reconstitutes the <code>FHashSet</code> instance from a stream.
16391639
*/
1640-
private void readObject(java.io.ObjectInputStream strm)
1641-
throws java.io.IOException, ClassNotFoundException {
1640+
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
1641+
hash_code = Integer.MIN_VALUE;
16421642
strm.defaultReadObject(); // reads `comp'
16431643
int size = strm.readInt();
16441644
tree = null;

com/ergy/fset/FLinkedHashMap.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,6 @@ public Map.Entry<Key, Val> arb() {
6666
return (Map.Entry<Key, Val>)FHashMap.arb(map_tree);
6767
}
6868

69-
public Key firstKey() {
70-
return (Key)FHashMap.firstKey(map_tree);
71-
}
72-
73-
public Key lastKey() {
74-
return (Key)FHashMap.lastKey(map_tree);
75-
}
76-
7769
public boolean contains(Map.Entry<Key, Val> entry) {
7870
Key key = entry.getKey();
7971
Object val = FHashMap.get(map_tree, key, hashCode(key));
@@ -332,6 +324,7 @@ private void writeObject(ObjectOutputStream strm) throws IOException {
332324
* Reconstitutes the <code>FLinkedHashMap</code> instance from a stream.
333325
*/
334326
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
327+
hash_code = Integer.MIN_VALUE;
335328
strm.defaultReadObject(); // reads `dflt'
336329
int size = strm.readInt();
337330
map_tree = null;

com/ergy/fset/FLinkedHashSet.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99

1010
package com.ergy.fset;
1111

12-
import java.util.*;
13-
1412
import java.io.IOException;
1513
import java.io.ObjectInputStream;
1614
import java.io.ObjectOutputStream;
1715
import java.io.Serializable;
16+
import java.util.*;
1817

1918

2019
/**
@@ -222,7 +221,7 @@ private static int hashCode(Object x) {
222221
* @serialData Emits the internal data of the set, including the size of the set
223222
* [<code>int</code>]; and the elements in order [<code>Object</code>s].
224223
*/
225-
private void writeObject(java.io.ObjectOutputStream strm) throws java.io.IOException {
224+
private void writeObject(ObjectOutputStream strm) throws IOException {
226225
strm.defaultWriteObject(); // writes `comp'
227226
strm.writeInt(size());
228227
for (Object e : this)
@@ -232,8 +231,8 @@ private void writeObject(java.io.ObjectOutputStream strm) throws java.io.IOExcep
232231
/**
233232
* Reconstitutes the <code>FLinkedHashSet</code> instance from a stream.
234233
*/
235-
private void readObject(java.io.ObjectInputStream strm)
236-
throws java.io.IOException, ClassNotFoundException {
234+
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
235+
hash_code = Integer.MIN_VALUE;
237236
strm.defaultReadObject(); // reads `comp'
238237
int size = strm.readInt();
239238
set_tree = null;

com/ergy/fset/FTreeList.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99

1010
package com.ergy.fset;
11+
12+
import java.io.IOException;
13+
import java.io.ObjectInputStream;
14+
import java.io.ObjectOutputStream;
15+
import java.io.Serializable;
1116
import java.util.*;
1217

1318
/**
@@ -47,7 +52,7 @@
4752

4853
public class FTreeList<Elt>
4954
extends AbstractFList<Elt>
50-
implements Comparable<FTreeList<Elt>>, java.io.Serializable
55+
implements Comparable<FTreeList<Elt>>, Serializable
5156
{
5257

5358
/**
@@ -1008,8 +1013,7 @@ public void set(Object o) {
10081013
* uses; the size of the list [<code>int</code>]; and the elements in order
10091014
* [<code>Object</code>s].
10101015
*/
1011-
private void writeObject(java.io.ObjectOutputStream strm)
1012-
throws java.io.IOException {
1016+
private void writeObject(ObjectOutputStream strm) throws IOException {
10131017
strm.defaultWriteObject(); // writes `elt_comp'
10141018
strm.writeInt(size());
10151019
for (Iterator it=iterator(); it.hasNext(); )
@@ -1019,8 +1023,8 @@ private void writeObject(java.io.ObjectOutputStream strm)
10191023
/**
10201024
* Reconstitutes the <code>FTreeSet</code> instance from a stream.
10211025
*/
1022-
private void readObject(java.io.ObjectInputStream strm)
1023-
throws java.io.IOException, ClassNotFoundException {
1026+
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
1027+
hash_code = Integer.MIN_VALUE;
10241028
strm.defaultReadObject(); // reads `elt_comp'
10251029
int size = strm.readInt();
10261030
Object[] ary = new Object[size];

com/ergy/fset/FTreeMap.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99

1010
package com.ergy.fset;
11+
12+
import java.io.IOException;
13+
import java.io.ObjectInputStream;
14+
import java.io.ObjectOutputStream;
15+
import java.io.Serializable;
1116
import java.util.*;
1217

1318
/**
@@ -106,7 +111,7 @@
106111
* used for the values). Thus, under these circumstances, the user must be sure that
107112
* the value objects implement <code>Comparable</code>.
108113
*
109-
* <p><code>FTreeMap</code> implements {@link java.io.Serializable}; an instance
114+
* <p><code>FTreeMap</code> implements {@link Serializable}; an instance
110115
* of it is serializable provided that all keys and values it contains, the
111116
* <code>Comparator</code> it uses if any, and the default value if nonnull, are
112117
* serializable.
@@ -118,7 +123,7 @@
118123

119124
public class FTreeMap<Key, Val>
120125
extends AbstractFMap<Key, Val>
121-
implements Comparable<FTreeMap<Key, Val>>, SortedMap<Key, Val>, java.io.Serializable
126+
implements Comparable<FTreeMap<Key, Val>>, SortedMap<Key, Val>, Serializable
122127
{
123128

124129
/**
@@ -2214,8 +2219,7 @@ public void remove() {
22142219
* comparator it uses; the size of the map [<code>int</code>]; and the key/value
22152220
* pairs in key order [<code>Object</code>s].
22162221
*/
2217-
private void writeObject(java.io.ObjectOutputStream strm)
2218-
throws java.io.IOException {
2222+
private void writeObject(ObjectOutputStream strm) throws IOException {
22192223
strm.defaultWriteObject(); // writes `comp' and `dflt'
22202224
strm.writeInt(size());
22212225
for (Map.Entry ment : this) {
@@ -2228,8 +2232,8 @@ private void writeObject(java.io.ObjectOutputStream strm)
22282232
/**
22292233
* Reconstitutes the <code>FTreeMap</code> instance from a stream.
22302234
*/
2231-
private void readObject(java.io.ObjectInputStream strm)
2232-
throws java.io.IOException, ClassNotFoundException {
2235+
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
2236+
hash_code = Integer.MIN_VALUE;
22332237
strm.defaultReadObject(); // reads `comp' and `dflt'
22342238
int size = strm.readInt();
22352239
tree = null;

com/ergy/fset/FTreeSet.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99

1010
package com.ergy.fset;
11+
12+
import java.io.IOException;
13+
import java.io.ObjectInputStream;
14+
import java.io.ObjectOutputStream;
15+
import java.io.Serializable;
1116
import java.util.*;
1217

1318
/**
@@ -71,7 +76,7 @@
7176
* equivalent but unequal elements, it does so with some loss of efficiency. As
7277
* long as these are rare, however, the cost will not be significant.
7378
*
74-
* <p><code>FTreeSet</code> implements {@link java.io.Serializable}; an instance
79+
* <p><code>FTreeSet</code> implements {@link Serializable}; an instance
7580
* of it is serializable provided that all elements it contains, and the
7681
* <code>Comparator</code> it uses if any, are serializable.
7782
*
@@ -84,7 +89,7 @@
8489

8590
public final class FTreeSet<Elt>
8691
extends AbstractFSet<Elt>
87-
implements SortedSet<Elt>, Comparable<FTreeSet<Elt>>, java.io.Serializable
92+
implements SortedSet<Elt>, Comparable<FTreeSet<Elt>>, Serializable
8893
{
8994

9095
/**
@@ -1777,8 +1782,7 @@ public void remove () {
17771782
* comparator it uses; the size of the set [<code>int</code>]; and the
17781783
* elements in order [<code>Object</code>s].
17791784
*/
1780-
private void writeObject(java.io.ObjectOutputStream strm)
1781-
throws java.io.IOException {
1785+
private void writeObject(ObjectOutputStream strm) throws IOException {
17821786
strm.defaultWriteObject(); // writes `comp'
17831787
strm.writeInt(size());
17841788
for (Object e : this)
@@ -1788,8 +1792,8 @@ private void writeObject(java.io.ObjectOutputStream strm)
17881792
/**
17891793
* Reconstitutes the <code>FTreeSet</code> instance from a stream.
17901794
*/
1791-
private void readObject(java.io.ObjectInputStream strm)
1792-
throws java.io.IOException, ClassNotFoundException {
1795+
private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException {
1796+
hash_code = Integer.MIN_VALUE;
17931797
strm.defaultReadObject(); // reads `comp'
17941798
int size = strm.readInt();
17951799
tree = null;

com/ergy/fset/TestSuite.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public static void main(String[] args) {
4848
FHashSet<MyInteger> fhs = testFHashSet(rand, i);
4949
//FSet pchs = testFCachedHashSet(rand, i);
5050
testFLinkedHashSet(rand, i);
51+
testFLinkedHashMap(rand, i);
5152
testFTreeMap(rand, i, fts);
5253
testFHashMap(rand, i, fhs);
5354
//testFCachedHashMap(rand, i, pchs);
@@ -379,7 +380,7 @@ static FTreeSet<MyInteger> testFTreeSet(Random rand, int i) {
379380
ObjectInputStream ois = new ObjectInputStream(fis);
380381
FSet<MyInteger> nftsser = (FSet<MyInteger>)ois.readObject();
381382
ois.close();
382-
if (!ftsser.equals(nftsser)) {
383+
if (!ftsser.equals(nftsser) || ftsser.hashCode() != nftsser.hashCode()) {
383384
println("FTreeSet read/write failed on iteration " + i);
384385
exit();
385386
}
@@ -660,7 +661,7 @@ static FHashSet<MyInteger> testFHashSet(Random rand, int i) {
660661
ObjectInputStream ois = new ObjectInputStream(fis);
661662
FSet<MyInteger> nfhsser = (FSet<MyInteger>)ois.readObject();
662663
ois.close();
663-
if (!fhsser.equals(nfhsser)) {
664+
if (!fhsser.equals(nfhsser) || fhsser.hashCode() != nfhsser.hashCode()) {
664665
println("FHashSet read/write failed on iteration " + i);
665666
exit();
666667
}
@@ -739,8 +740,8 @@ static void testFLinkedHashSet(Random rand, int i) {
739740
ObjectInputStream ois = new ObjectInputStream(fis);
740741
FSet<Integer> nfhsser = (FSet<Integer>)ois.readObject();
741742
ois.close();
742-
if (!fhsser.equals(nfhsser)) {
743-
println("FHashSet read/write failed on iteration " + i);
743+
if (!fhsser.equals(nfhsser) || fhsser.hashCode() != nfhsser.hashCode()) {
744+
println("FLinkedHashSet read/write failed on iteration " + i);
744745
exit();
745746
}
746747
flhs0_it = flhs0.iterator();
@@ -1039,7 +1040,7 @@ static FSet testFCachedHashSet(Random rand, int i) {
10391040
ObjectInputStream ois = new ObjectInputStream(fis);
10401041
FSet nfhsser = (FSet)ois.readObject();
10411042
ois.close();
1042-
if (!fhsser.equals(nfhsser)) {
1043+
if (!fhsser.equals(nfhsser) || fhsser.hashCode() != nfhsser.hashCode()) {
10431044
println("FCachedHashSet read/write failed on iteration " + i);
10441045
exit();
10451046
}
@@ -1352,7 +1353,7 @@ static void testFTreeMap(Random rand, int i, FTreeSet<MyInteger> set) {
13521353
FMap<MyInteger, MyInteger> nftmser =
13531354
(FMap<MyInteger, MyInteger>)ois.readObject();
13541355
ois.close();
1355-
if (!ftmser.equals(nftmser)) {
1356+
if (!ftmser.equals(nftmser) || ftmser.hashCode() != nftmser.hashCode()) {
13561357
println("FTreeMap read/write failed on iteration " + i);
13571358
exit();
13581359
}
@@ -1543,7 +1544,7 @@ static void testFHashMap(Random rand, int i, FHashSet<MyInteger> set) {
15431544
ObjectInputStream ois = new ObjectInputStream(fis);
15441545
FMap<MyInteger, MyInteger> nfhmser = (FMap<MyInteger, MyInteger>)ois.readObject();
15451546
ois.close();
1546-
if (!fhmser.equals(nfhmser)) {
1547+
if (!fhmser.equals(nfhmser) || fhmser.hashCode() != nfhmser.hashCode()) {
15471548
println("FHashMap read/write failed on iteration " + i);
15481549
exit();
15491550
}
@@ -1731,7 +1732,7 @@ static void testFCachedHashMap(Random rand, int i, FSet set) {
17311732
ObjectInputStream ois = new ObjectInputStream(fis);
17321733
FMap nfhmser = (FMap)ois.readObject();
17331734
ois.close();
1734-
if (!fhmser.equals(nfhmser)) {
1735+
if (!fhmser.equals(nfhmser) || fhmser.hashCode() != nfhmser.hashCode()) {
17351736
println("FCachedHashMap read/write failed on iteration " + i);
17361737
exit();
17371738
}
@@ -1792,8 +1793,8 @@ static void testFLinkedHashMap(Random rand, int i) {
17921793
ObjectInputStream ois = new ObjectInputStream(fis);
17931794
FMap<Integer, Integer> nfhmser = (FMap<Integer, Integer>)ois.readObject();
17941795
ois.close();
1795-
if (!fhmser.equals(nfhmser)) {
1796-
println("FHashMap read/write failed on iteration " + i);
1796+
if (!fhmser.equals(nfhmser) || fhmser.hashCode() != nfhmser.hashCode()) {
1797+
println("FLinkedHashMap read/write failed on iteration " + i);
17971798
exit();
17981799
}
17991800
flhm0_it = flhm0.iterator();
@@ -2044,12 +2045,15 @@ static void testFTreeList(Random rand, int i) {
20442045
FileOutputStream fos = new FileOutputStream("ftl.tmp");
20452046
ObjectOutputStream oos = new ObjectOutputStream(fos);
20462047
oos.writeObject(ftlser);
2048+
oos.writeObject(ftlser);
20472049
oos.close();
20482050
FileInputStream fis = new FileInputStream("ftl.tmp");
20492051
ObjectInputStream ois = new ObjectInputStream(fis);
2050-
FList<MyInteger> nftlser = (FList<MyInteger>)ois.readObject();
2052+
FList<MyInteger> nftlser0 = (FList<MyInteger>)ois.readObject();
2053+
FList<MyInteger> nftlser1 = (FList<MyInteger>)ois.readObject();
20512054
ois.close();
2052-
if (!ftlser.equals(nftlser)) {
2055+
if (!ftlser.equals(nftlser0) || !ftlser.equals(nftlser1) ||
2056+
ftlser.hashCode() != nftlser0.hashCode()) {
20532057
println("FTreeList read/write failed on iteration " + i);
20542058
exit();
20552059
}

0 commit comments

Comments
 (0)