diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index dfbb5c718..39771212e 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -30,6 +30,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -965,16 +966,22 @@ public class DataHelper { out.write(data); } - public static List sortStructures(Collection dataStructures) { - if (dataStructures == null) return new ArrayList(); - ArrayList rv = new ArrayList(dataStructures.size()); - TreeMap tm = new TreeMap(); - for (Iterator iter = dataStructures.iterator(); iter.hasNext();) { - DataStructure struct = (DataStructure) iter.next(); + /** + * Sort based on the Hash of the DataStructure + * Warning - relatively slow. + * Only used by RouterInfo + * Why? Just because it has to be consistent so signing will work? + * How to spec as returning the same type as the param? + */ + public static List sortStructures(Collection dataStructures) { + if (dataStructures == null) return Collections.EMPTY_LIST; + ArrayList rv = new ArrayList(dataStructures.size()); + TreeMap tm = new TreeMap(); + for (DataStructure struct : dataStructures) { tm.put(struct.calculateHash().toString(), struct); } - for (Iterator iter = tm.values().iterator(); iter.hasNext();) { - rv.add(iter.next()); + for (DataStructure struct : tm.values()) { + rv.add(struct); } return rv; } diff --git a/core/java/src/net/i2p/data/RouterInfo.java b/core/java/src/net/i2p/data/RouterInfo.java index 3f4caa711..20de623e8 100644 --- a/core/java/src/net/i2p/data/RouterInfo.java +++ b/core/java/src/net/i2p/data/RouterInfo.java @@ -13,6 +13,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Iterator; @@ -264,14 +265,16 @@ public class RouterInfo extends DataStructureImpl { try { _identity.writeBytes(out); DataHelper.writeDate(out, new Date(_published)); - if (isHidden()) { + int sz = _addresses.size(); + if (sz <= 0 || isHidden()) { // Do not send IP address to peers in hidden mode DataHelper.writeLong(out, 1, 0); } else { - DataHelper.writeLong(out, 1, _addresses.size()); - List addresses = DataHelper.sortStructures(_addresses); - for (Iterator iter = addresses.iterator(); iter.hasNext();) { - RouterAddress addr = (RouterAddress) iter.next(); + DataHelper.writeLong(out, 1, sz); + Collection addresses = _addresses; + if (sz > 1) + addresses = (Collection) DataHelper.sortStructures(addresses); + for (RouterAddress addr : addresses) { addr.writeBytes(out); } } @@ -279,12 +282,16 @@ public class RouterInfo extends DataStructureImpl { // answer: they're always empty... they're a placeholder for one particular // method of trusted links, which isn't implemented in the router // at the moment, and may not be later. - // fixme to reduce objects - if (_peers == null) write 0 - DataHelper.writeLong(out, 1, _peers.size()); - List peers = DataHelper.sortStructures(_peers); - for (Iterator iter = peers.iterator(); iter.hasNext();) { - Hash peerHash = (Hash) iter.next(); - peerHash.writeBytes(out); + // fixme to reduce objects - allow _peers == null + int psz = _peers.size(); + DataHelper.writeLong(out, 1, psz); + if (psz > 0) { + Collection peers = _peers; + if (psz > 1) + peers = (Collection) DataHelper.sortStructures(peers); + for (Hash peerHash : peers) { + peerHash.writeBytes(out); + } } DataHelper.writeProperties(out, _options); } catch (IOException ioe) {