TreeMap.navigableKeySet().descendingIterator() sequence ?
Christopher Hegarty - Sun Microsystems Ireland
Christopher.Hegarty at Sun.COM
Sun Apr 20 09:50:15 UTC 2008
Hi Martin,
I (OpenJDK user chegar) approve the changes that you made to:
src/share/classes/java/util/TreeMap.java
test/java/util/Collection/MOAT.java
test/java/util/NavigableMap/LockStep.java
The only comment I have is that you may want to add the bug number, CR
6691185, to the @bug tag in the testcases. Do you still have integration
access?
I can take care of the JDK 6 integration.
-Chris.
Martin Buchholz wrote:
> Alan, thanks for filing the bug.
>
> Charlie, thanks for the review. However, since you are not (yet?)
> an OpenJDK committer, I will still need an official review from Doug
> (or Alan?)
>
> I noticed there was another test case, NavigableMap/LockStep.java,
> that "almost" tested the faulty code.
>
> I include a change to that test case as well, below
> (as well as making the test case a little more maintainble).
>
> diff --git a/test/java/util/NavigableMap/LockStep.java
> b/test/java/util/NavigableMap/LockStep.java
> --- a/test/java/util/NavigableMap/LockStep.java
> +++ b/test/java/util/NavigableMap/LockStep.java
> @@ -159,6 +159,7 @@ public class LockStep {
> Object[] a = new Object[1]; a[0] = Boolean.TRUE;
> equal(c.toArray(a), a);
> equal(a[0], null);
> + check(! c.iterator().hasNext());
> }
>
> static void testEmptySet(Set<?> c) {
> @@ -262,6 +263,16 @@ public class LockStep {
> }
> }
>
> + static void equalIterators(final Iterator<?> it1,
> + final Iterator<?> it2) {
> + while (it1.hasNext()) {
> + if (maybe(2))
> + check(it2.hasNext());
> + equal(it1.next(), it2.next());
> + }
> + check(! it2.hasNext());
> + }
> +
> static void equalNavigableSetsLeaf(final NavigableSet s1,
> final NavigableSet s2) {
> equal2(s1, s2);
> @@ -273,6 +284,8 @@ public class LockStep {
> equal(s1.first(), s2.first());
> equal(s1.last(), s2.last());
> }
> + equalIterators(s1.iterator(), s2.iterator());
> + equalIterators(s1.descendingIterator(), s2.descendingIterator());
> checkNavigableSet(s1);
> checkNavigableSet(s2);
> }
> @@ -493,30 +506,23 @@ public class LockStep {
>
> static MapFrobber randomAdder(NavigableMap m) {
> final Integer k = unusedKey(m);
> - MapFrobber f;
> - switch (rnd.nextInt(4)) {
> - case 0: f = new MapFrobber() {void frob(NavigableMap m) {
> - equal(m.put(k, k+1), null);
> - equal(m.get(k), k+1);
> - if (maybe(4)) {
> - equal(m.put(k, k+1), k+1);
> - equal(m.get(k), k+1);}}};
> - break;
> - case 1: f = new MapFrobber() {void frob(NavigableMap m) {
> - m.descendingMap().put(k, k+1);
> - equal(m.get(k), k+1);}};
> - break;
> - case 2: f = new MapFrobber() {void frob(NavigableMap m) {
> - m.tailMap(k,true).headMap(k,true).put(k,k+1);}};
> - break;
> - case 3: f = new MapFrobber() {void frob(NavigableMap m) {
> - m.tailMap(k,true).headMap(k,true).descendingMap().put(k,k+1);}};
> - break;
> - default: throw new Error();
> - }
> - final MapFrobber ff = f;
> + final MapFrobber[] randomAdders = {
> + new MapFrobber() {void frob(NavigableMap m) {
> + equal(m.put(k, k+1), null);
> + equal(m.get(k), k+1);
> + if (maybe(4)) {
> + equal(m.put(k, k+1), k+1);
> + equal(m.get(k), k+1);}}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + m.descendingMap().put(k, k+1);
> + equal(m.get(k), k+1);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + m.tailMap(k,true).headMap(k,true).put(k,k+1);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + m.tailMap(k,true).headMap(k,true).descendingMap().put(k,k+1);}}
> + };
> return new MapFrobber() {void frob(NavigableMap m) {
> - ff.frob(m);
> + randomAdders[rnd.nextInt(randomAdders.length)].frob(m);
> if (maybe(2)) equal(m.get(k), k+1);
> if (maybe(4)) {
> equal(m.put(k, k+1), k+1);
> @@ -525,26 +531,19 @@ public class LockStep {
>
> static SetFrobber randomAdder(NavigableSet s) {
> final Integer e = unusedElt(s);
> - SetFrobber f;
> - switch (rnd.nextInt(4)) {
> - case 0: f = new SetFrobber() {void frob(NavigableSet s) {
> - check(s.add(e));}};
> - break;
> - case 1: f = new SetFrobber() {void frob(NavigableSet s) {
> - s.descendingSet().add(e);}};
> - break;
> - case 2: f = new SetFrobber() {void frob(NavigableSet s) {
> - s.tailSet(e,true).headSet(e,true).add(e);}};
> - break;
> - case 3: f = new SetFrobber() {void frob(NavigableSet s) {
> - s.descendingSet().tailSet(e,true).headSet(e,true).add(e);}};
> - break;
> - default: throw new Error();
> - }
> - final SetFrobber ff = f;
> + final SetFrobber[] randomAdders = {
> + new SetFrobber() {void frob(NavigableSet s) {
> + check(s.add(e));}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + s.descendingSet().add(e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + s.tailSet(e,true).headSet(e,true).add(e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + s.descendingSet().tailSet(e,true).headSet(e,true).add(e);}}
> + };
> return new SetFrobber() {void frob(NavigableSet s) {
> if (maybe(2)) check(! s.contains(e));
> - ff.frob(s);
> + randomAdders[rnd.nextInt(randomAdders.length)].frob(s);
> if (maybe(2)) check(! s.add(e));
> if (maybe(2)) check(s.contains(e));}};
> }
> @@ -605,89 +604,112 @@ public class LockStep {
>
> static MapFrobber randomRemover(NavigableMap m) {
> final Integer k = usedKey(m);
> - switch (rnd.nextInt(7)) {
> - default: throw new Error();
> - case 0: return new MapFrobber() {void frob(NavigableMap m) {
> - Map.Entry e = m.firstEntry();
> - equal(m.pollFirstEntry(), e);
> - checkUnusedKey(m, e.getKey());}};
> - case 1: return new MapFrobber() {void frob(NavigableMap m) {
> - Map.Entry e = m.lastEntry();
> - equal(m.pollLastEntry(), e);
> - checkUnusedKey(m, e.getKey());}};
> - case 2: return new MapFrobber() {void frob(NavigableMap m) {
> - check(m.remove(k) != null);
> - checkUnusedKey(m, k);}};
> - case 3: return new MapFrobber() {void frob(NavigableMap m) {
> - m.subMap(k, true, k, true).clear();
> - checkUnusedKey(m, k);}};
> - case 4: return new MapFrobber() {void frob(NavigableMap m) {
> - m.descendingMap().subMap(k, true, k, true).clear();
> - checkUnusedKey(m, k);}};
> - case 5: return new MapFrobber() {void frob(NavigableMap m) {
> - final Iterator it = m.keySet().iterator();
> - while (it.hasNext())
> - if (it.next().equals(k)) {
> - it.remove();
> - if (maybe(2))
> - THROWS(IllegalStateException.class,
> - new Fun(){void f(){ it.remove(); }});
> - }
> - checkUnusedKey(m, k);}};
> - case 6: return new MapFrobber() {void frob(NavigableMap m) {
> - final Iterator<Map.Entry> it = m.entrySet().iterator();
> - while (it.hasNext())
> - if (it.next().getKey().equals(k)) {
> - it.remove();
> - if (maybe(2))
> - THROWS(IllegalStateException.class, remover(it));
> - }
> - checkUnusedKey(m, k);}};
> - }
> + final MapFrobber[] randomRemovers = {
> + new MapFrobber() {void frob(NavigableMap m) {
> + Map.Entry e = m.firstEntry();
> + equal(m.pollFirstEntry(), e);
> + checkUnusedKey(m, e.getKey());}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + Map.Entry e = m.lastEntry();
> + equal(m.pollLastEntry(), e);
> + checkUnusedKey(m, e.getKey());}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + check(m.remove(k) != null);
> + checkUnusedKey(m, k);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + m.subMap(k, true, k, true).clear();
> + checkUnusedKey(m, k);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + m.descendingMap().subMap(k, true, k, true).clear();
> + checkUnusedKey(m, k);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + final Iterator it = m.keySet().iterator();
> + while (it.hasNext())
> + if (it.next().equals(k)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class,
> + new Fun(){void f(){ it.remove(); }});
> + }
> + checkUnusedKey(m, k);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + final Iterator it = m.navigableKeySet().descendingIterator();
> + while (it.hasNext())
> + if (it.next().equals(k)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class,
> + new Fun(){void f(){ it.remove(); }});
> + }
> + checkUnusedKey(m, k);}},
> + new MapFrobber() {void frob(NavigableMap m) {
> + final Iterator<Map.Entry> it = m.entrySet().iterator();
> + while (it.hasNext())
> + if (it.next().getKey().equals(k)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class, remover(it));
> + }
> + checkUnusedKey(m, k);}},
> + };
> +
> + return randomRemovers[rnd.nextInt(randomRemovers.length)];
> }
>
> static SetFrobber randomRemover(NavigableSet s) {
> final Integer e = usedElt(s);
> - switch (rnd.nextInt(7)) {
> - default: throw new Error();
> - case 0: return new SetFrobber() {void frob(NavigableSet s) {
> - Object e = s.first();
> - equal(s.pollFirst(), e);
> - checkUnusedElt(s, e);}};
> - case 1: return new SetFrobber() {void frob(NavigableSet s) {
> - Object e = s.last();
> - equal(s.pollLast(), e);
> - checkUnusedElt(s, e);}};
> - case 2: return new SetFrobber() {void frob(NavigableSet s) {
> - check(s.remove(e));
> - checkUnusedElt(s, e);}};
> - case 3: return new SetFrobber() {void frob(NavigableSet s) {
> - s.subSet(e, true, e, true).clear();
> - checkUnusedElt(s, e);}};
> - case 4: return new SetFrobber() {void frob(NavigableSet s) {
> - s.descendingSet().subSet(e, true, e, true).clear();
> - checkUnusedElt(s, e);}};
> - case 5: return new SetFrobber() {void frob(NavigableSet s) {
> - final Iterator it = s.iterator();
> - while (it.hasNext())
> - if (it.next().equals(e)) {
> - it.remove();
> - if (maybe(2))
> - THROWS(IllegalStateException.class,
> - new Fun(){void f(){ it.remove(); }});
> - }
> - checkUnusedElt(s, e);}};
> - case 6: return new SetFrobber() {void frob(NavigableSet s) {
> - final Iterator it = s.descendingSet().iterator();
> - while (it.hasNext())
> - if (it.next().equals(e)) {
> - it.remove();
> - if (maybe(2))
> - THROWS(IllegalStateException.class,
> - new Fun(){void f(){ it.remove(); }});
> - }
> - checkUnusedElt(s, e);}};
> - }
> +
> + final SetFrobber[] randomRemovers = {
> + new SetFrobber() {void frob(NavigableSet s) {
> + Object e = s.first();
> + equal(s.pollFirst(), e);
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + Object e = s.last();
> + equal(s.pollLast(), e);
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + check(s.remove(e));
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + s.subSet(e, true, e, true).clear();
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + s.descendingSet().subSet(e, true, e, true).clear();
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + final Iterator it = s.iterator();
> + while (it.hasNext())
> + if (it.next().equals(e)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class,
> + new Fun(){void f(){ it.remove(); }});
> + }
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + final Iterator it = s.descendingSet().iterator();
> + while (it.hasNext())
> + if (it.next().equals(e)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class,
> + new Fun(){void f(){ it.remove(); }});
> + }
> + checkUnusedElt(s, e);}},
> + new SetFrobber() {void frob(NavigableSet s) {
> + final Iterator it = s.descendingIterator();
> + while (it.hasNext())
> + if (it.next().equals(e)) {
> + it.remove();
> + if (maybe(2))
> + THROWS(IllegalStateException.class,
> + new Fun(){void f(){ it.remove(); }});
> + }
> + checkUnusedElt(s, e);}}
> + };
> +
> + return randomRemovers[rnd.nextInt(randomRemovers.length)];
> }
>
> static void lockStep(NavigableMap m1,
>
>
> Martin
>
> On Sat, Apr 19, 2008 at 2:07 PM, charlie hunt <charlie.hunt at sun.com> wrote:
>> Alan Bateman wrote:
>>
>>> Martin Buchholz wrote:
>>>
>>>> :
>>>>
>>>> 2. Bug creation from Charlie (or some other person empowered to do so)
>>>> I suggest making this bug P2-S2.
>>>>
>>>> I will need the bug id and synopsis to create the proper mercurial
>> comment.
>>>>
>>> I don't know if Charlie is online today, but as you seem to be ready to
>> create the change-set, I've created java/classes_util bug:
>>> 6691185: (coll) TreeMap.navigableKeySet's descendingIterator method
>> starts at first instead of last entry
>>> with a link to this thread. The synopsis can be changed if you want
>> something different.
>>> -Alan.
>>>
>> Alan, thanks for filing the bug. One less item on my list of things to do.
>> :-)
>>
>> Fwiw, I've looked at Martin's proposed changes. From the familiarity I've
>> gotten with TreeMap over the past week or two, the changes look good to me.
>>
>> charlie ...
>>
>>
>>
More information about the core-libs-dev
mailing list