Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/DistanceQuery.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/DistanceQuery.java	(revision 1076325)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/DistanceQuery.java	(working copy)
@@ -84,7 +84,16 @@
       public Query rewrite(IndexReader reader) throws IOException {
         return getSpanNearQuery(reader, fieldName, getBoost(), qf);
       }
-      
+
+      @Override
+      public int hashCode() {
+	return DistanceQuery.this.hashCode();
+      }
+    
+      @Override
+      public boolean equals(Object obj) {
+	return DistanceQuery.this.equals(obj);
+      }                                                     
     };
   }
   
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SimpleTerm.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SimpleTerm.java	(revision 1076325)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SimpleTerm.java	(working copy)
@@ -39,6 +39,10 @@
   
   public abstract String toStringUnquoted();
   
+  /** @deprecated Not normally used, to be removed from Lucene 5.0.
+   *   This class implementing Comparable is to be removed at the same time.
+   */
+  @Deprecated
   public int compareTo(SimpleTerm ost) {
     /* for ordering terms and prefixes before using an index, not used */
     return this.toStringUnquoted().compareTo( ost.toStringUnquoted());
@@ -96,6 +100,16 @@
                   /* luceneSubQueries all have default weight */
                   luceneSubQueries, BooleanClause.Occur.SHOULD); /* OR the subquery terms */ 
       }
+
+      @Override
+      public int hashCode() {
+	return SimpleTerm.this.hashCode();
+      }
+    
+      @Override
+      public boolean equals(Object obj) {
+	return SimpleTerm.this.equals(obj);
+      }                                                     
     };
   }
     
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SrndQuery.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SrndQuery.java	(revision 1076325)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/surround/query/SrndQuery.java	(working copy)
@@ -53,6 +53,9 @@
   
   public abstract Query makeLuceneQueryFieldNoBoost(String fieldName, BasicQueryFactory qf);
   
+  /** This method is used by {@link #hashCode()} and {@link #equals(Object)},
+   *  see LUCENE-2945.
+   */
   @Override
   public abstract String toString();
   
@@ -66,8 +69,30 @@
       throw new Error(cns);
     }
   }
-  
-/* An empty Lucene query */
+
+  /** For subclasses of {@link SrndQuery} within the package
+   *  {@link org.apache.lucene.queryParser.surround.query}
+   *  it is not necessary to override this method.
+   */
+  @Override
+  public int hashCode() {
+    return getClass().hashCode() ^ toString().hashCode();
+  }
+
+  /** For subclasses of {@link SrndQuery} within the package
+   *  {@link org.apache.lucene.queryParser.surround.query}
+   *  it is not necessary to override this method.
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == null)
+      return false;
+    if (! getClass().equals(obj.getClass()))
+      return false;
+    return toString().equals(obj.toString());
+  }
+
+  /** An empty Lucene query */
   public final static Query theEmptyLcnQuery = new BooleanQuery() { /* no changes allowed */
     @Override
     public void setBoost(float boost) {
