diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
index 3fb39ce96b9f43d6a5270dc8f7b344373fb1083d..ce4a0658ac8a7ac1b6889d0dd16df64e68a505b8 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
@@ -69,13 +69,12 @@ public class PeerCoordinator implements PeerListener
     this.storage = storage;
     this.listener = listener;
 
-    // Make a random list of piece numbers
+    // Make a list of pieces
     wantedPieces = new ArrayList();
     BitField bitfield = storage.getBitField();
     for(int i = 0; i < metainfo.getPieces(); i++)
       if (!bitfield.get(i))
-        wantedPieces.add(new Integer(i));
-    Collections.shuffle(wantedPieces);
+        wantedPieces.add(new Piece(i));
 
     // Install a timer to check the uploaders.
     timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD);
@@ -288,7 +287,7 @@ public class PeerCoordinator implements PeerListener
 
     synchronized(wantedPieces)
       {
-        return wantedPieces.contains(new Integer(piece));
+        return wantedPieces.contains(new Piece(piece));
       }
   }
 
@@ -306,8 +305,10 @@ public class PeerCoordinator implements PeerListener
         Iterator it = wantedPieces.iterator();
         while (it.hasNext())
           {
-            int i = ((Integer)it.next()).intValue();
+            Piece p = (Piece)it.next();
+            int i = p.getId();
             if (bitfield.get(i))
+              p.addPeer(peer);
               return true;
           }
       }
@@ -325,28 +326,38 @@ public class PeerCoordinator implements PeerListener
 
     synchronized(wantedPieces)
       {
-        Integer piece = null;
+        Piece piece = null;
+        Collections.sort(wantedPieces); // Sort in order of rarest first.
+        List requested = new ArrayList(); 
         Iterator it = wantedPieces.iterator();
         while (piece == null && it.hasNext())
           {
-            Integer i = (Integer)it.next();
-            if (havePieces.get(i.intValue()))
+            Piece p = (Piece)it.next();
+            if (havePieces.get(p.getId()) && !p.isRequested())
               {
-                it.remove();
-                piece = i;
+                piece = p;
               }
+            else if (p.isRequested()) 
+            {
+                requested.add(p);
+            }
           }
-
-        if (piece == null)
-          return -1;
-
-        // We add it back at the back of the list. It will be removed
-        // if gotPiece is called later. This means that the last
-        // couple of pieces might very well be asked from multiple
-        // peers but that is OK.
-        wantedPieces.add(piece);
-
-        return piece.intValue();
+        
+        //Only request a piece we've requested before if there's no other choice.
+        if (piece == null) {
+            Iterator it2 = requested.iterator();
+            while (piece == null && it2.hasNext())
+              {
+                Piece p = (Piece)it2.next();
+                if (havePieces.get(p.getId()))
+                  {
+                    piece = p;
+                  }
+              }
+            if (piece == null) return -1; //If we still can't find a piece we want, so be it.
+        }
+        piece.setRequested(true);
+        return piece.getId();
       }
   }
 
@@ -404,7 +415,7 @@ public class PeerCoordinator implements PeerListener
     
     synchronized(wantedPieces)
       {
-        Integer p = new Integer(piece);
+        Piece p = new Piece(piece);
         if (!wantedPieces.contains(p))
           {
             if (Snark.debug >= Snark.INFO)
diff --git a/apps/i2psnark/java/src/org/klomp/snark/Piece.java b/apps/i2psnark/java/src/org/klomp/snark/Piece.java
new file mode 100644
index 0000000000000000000000000000000000000000..d98421b99252babe3f3564b05d10f1d65c2e738c
--- /dev/null
+++ b/apps/i2psnark/java/src/org/klomp/snark/Piece.java
@@ -0,0 +1,35 @@
+package org.klomp.snark;
+
+import java.util.Set;
+import java.util.HashSet;
+
+public class Piece implements Comparable {
+
+    private int id;
+    private Set peers;
+    private boolean requested;
+    
+    public Piece(int id) {
+        this.id = id;
+        this.peers = new HashSet();
+    }
+    
+    public int compareTo(Object o) throws ClassCastException {
+        return this.peers.size() - ((Piece)o).peers.size();
+    }
+    
+    public boolean equals(Object o) {
+        if (o == null) return false;
+        try {
+            return this.id == ((Piece)o).id;
+        } catch (ClassCastException cce) {
+            return false;
+        }
+    }
+    
+    public int getId() { return this.id; }
+    public Set getPeers() { return this.peers; }
+    public boolean addPeer(Peer peer) { return this.peers.add(peer.getPeerID()); }
+    public boolean isRequested() { return this.requested; }
+    public void setRequested(boolean requested) { this.requested = requested; } 
+}