You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2017/03/04 18:03:41 UTC

commons-compress git commit: use builder pattern for LZ77 to simplify addition of optional parameters

Repository: commons-compress
Updated Branches:
  refs/heads/master 5375fd9dc -> 5170392a5


use builder pattern for LZ77 to simplify addition of optional parameters

also:

* use "back-reference" consistently in public API

* make maxBackReferenceLength default to minBackReferenceLength for
  silly values

* make parameter builder public for Snappy and LZ4

this change is here so people will be able to use

    createParameterBuilder().tunedForSpeed().build()

in the future.


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/5170392a
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/5170392a
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/5170392a

Branch: refs/heads/master
Commit: 5170392a5b1e7cd7dccd7e3ef4d6c7279022696d
Parents: 5375fd9
Author: Stefan Bodewig <bo...@apache.org>
Authored: Sat Mar 4 18:57:12 2017 +0100
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Sat Mar 4 19:03:27 2017 +0100

----------------------------------------------------------------------
 .../lz4/BlockLZ4CompressorOutputStream.java     |  30 ++-
 .../compressors/lz77support/LZ77Compressor.java |  22 +--
 .../compressors/lz77support/Parameters.java     | 197 ++++++++++++++-----
 .../snappy/SnappyCompressorOutputStream.java    |  15 +-
 .../lz77support/LZ77CompressorTest.java         |  44 +++--
 .../compressors/lz77support/ParametersTest.java |  73 ++++---
 .../compressors/snappy/SnappyRoundtripTest.java |  16 +-
 7 files changed, 283 insertions(+), 114 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java
index f7ba28d..d3249db 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java
@@ -98,10 +98,22 @@ public class BlockLZ4CompressorOutputStream extends CompressorOutputStream {
      * @throws IOException if reading fails
      */
     public BlockLZ4CompressorOutputStream(final OutputStream os) throws IOException {
+        this(os, createParameterBuilder().build());
+    }
+
+    /**
+     * Creates a new LZ4 output stream.
+     *
+     * @param os
+     *            An OutputStream to read compressed data from
+     * @param params
+     *            The parameters to use for LZ77 compression.
+     *
+     * @throws IOException if reading fails
+     */
+    public BlockLZ4CompressorOutputStream(final OutputStream os, Parameters params) throws IOException {
         this.os = os;
-        int maxLen = BlockLZ4CompressorInputStream.WINDOW_SIZE - 1;
-        compressor = new LZ77Compressor(new Parameters(BlockLZ4CompressorInputStream.WINDOW_SIZE,
-            MIN_BACK_REFERENCE_LENGTH, maxLen, maxLen, maxLen),
+        compressor = new LZ77Compressor(params,
             new LZ77Compressor.Callback() {
                 public void accept(LZ77Compressor.Block block) throws IOException {
                     //System.err.println(block);
@@ -388,6 +400,18 @@ public class BlockLZ4CompressorOutputStream extends CompressorOutputStream {
         pairs.add(replacement);
     }
 
+    /**
+     * Returns a builder correctly configured for the LZ4 algorithm.
+     */
+    public static Parameters.Builder createParameterBuilder() {
+        int maxLen = BlockLZ4CompressorInputStream.WINDOW_SIZE - 1;
+        return Parameters.builder(BlockLZ4CompressorInputStream.WINDOW_SIZE)
+            .withMinBackReferenceLength(MIN_BACK_REFERENCE_LENGTH)
+            .withMaxBackReferenceLength(maxLen)
+            .withMaxOffset(maxLen)
+            .withMaxLiteralLength(maxLen);
+    }
+
     final static class Pair {
         private final Deque<byte[]> literals = new LinkedList<>();
         private int brOffset, brLength;

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java b/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
index 63b880a..487dee2 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
@@ -63,13 +63,13 @@ import java.util.Arrays;
  *  buffer of twice of <code>windowSize</code> - real world values are
  *  in the area of 32k.</dd>
  *
- *  <dt><code>minMatchLength</code></dt>
- *  <dd>Minimal length of a match found. A true minimum of 3 is
+ *  <dt><code>minBackReferenceLength</code></dt>
+ *  <dd>Minimal length of a back-reference found. A true minimum of 3 is
  *  hard-coded inside of this implemention but bigger lengths can be
  *  configured.</dd>
  *
- *  <dt><code>maxMatchLength</code></dt>
- *  <dd>Maximal length of a match found.</dd>
+ *  <dt><code>maxBackReferenceLength</code></dt>
+ *  <dd>Maximal length of a back-reference found.</dd>
  *
  *  <dt><code>maxOffset</code></dt>
  *  <dd>Maximal offset of a back-reference.</dd>
@@ -135,7 +135,7 @@ public class LZ77Compressor {
         }
     }
     /**
-     * Represents a back-reference to a match.
+     * Represents a back-reference.
      */
     public static final class BackReference extends Block {
         private final int offset, length;
@@ -144,14 +144,14 @@ public class LZ77Compressor {
             this.length = length;
         }
         /**
-         * Provides the offset of the match.
+         * Provides the offset of the back-reference.
          * @return the offset
          */
         public int getOffset() {
             return offset;
         }
         /**
-         * Provides the length of the match.
+         * Provides the length of the back-reference.
          * @return the length
          */
         public int getLength() {
@@ -357,7 +357,7 @@ public class LZ77Compressor {
         }
         System.arraycopy(data, off, window, currentPosition + lookahead, len);
         lookahead += len;
-        if (!initialized && lookahead >= params.getMinMatchLength()) {
+        if (!initialized && lookahead >= params.getMinBackReferenceLength()) {
             initialize();
         }
         if (initialized) {
@@ -393,7 +393,7 @@ public class LZ77Compressor {
     }
 
     private void compress() throws IOException {
-        final int minMatch = params.getMinMatchLength();
+        final int minMatch = params.getMinBackReferenceLength();
 
         while (lookahead >= minMatch) {
             catchUpMissedInserts();
@@ -475,9 +475,9 @@ public class LZ77Compressor {
      * longest match as a side effect.</p>
      */
     private int longestMatch(int matchHead) {
-        final int minLength = params.getMinMatchLength();
+        final int minLength = params.getMinBackReferenceLength();
         int longestMatchLength = minLength - 1;
-        final int maxPossibleLength = Math.min(params.getMaxMatchLength(), lookahead);
+        final int maxPossibleLength = Math.min(params.getMaxBackReferenceLength(), lookahead);
         final int minIndex = Math.max(0, currentPosition - params.getMaxOffset());
         while (matchHead >= minIndex) {
             int currentLength = 0;

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/main/java/org/apache/commons/compress/compressors/lz77support/Parameters.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/compressors/lz77support/Parameters.java b/src/main/java/org/apache/commons/compress/compressors/lz77support/Parameters.java
index e4f02e1..3842dd9 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lz77support/Parameters.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz77support/Parameters.java
@@ -22,63 +22,152 @@ package org.apache.commons.compress.compressors.lz77support;
  * Parameters of the {@link LZ77Compressor compressor}.
  */
 public final class Parameters {
-    public static final int TRUE_MIN_MATCH_LENGTH = LZ77Compressor.NUMBER_OF_BYTES_IN_HASH;
-    private final int windowSize, minMatchLength, maxMatchLength, maxOffset, maxLiteralLength;
+    /**
+     * The hard-coded absolute minimal length of a back-reference.
+     */
+    public static final int TRUE_MIN_BACK_REFERENCE_LENGTH = LZ77Compressor.NUMBER_OF_BYTES_IN_HASH;
 
     /**
-     * Initializes the compressor's parameters with a
-     * <code>minMatchLength</code> of 3 and <code>max*Length</code>
+     * Initializes the builder for the compressor's parameters with a
+     * <code>minBackReferenceLength</code> of 3 and <code>max*Length</code>
      * equal to <code>windowSize - 1</code>.
      *
+     * <p>It is recommended to not use this method directly but rather
+     * tune a pre-configured builder created by a format specific
+     * factory like {@link
+     * org.apache.commons.compress.compressors.snappy.SnappyCompressorOutputStream#createParameterBuilder}.</p>
+     *
      * @param windowSize the size of the sliding window - this
-     * determines the maximum offset a back-reference can take.
-     * @throws IllegalArgumentException if <code>windowSize</code>
-     * is smaller than <code>minMatchLength</code>.
+     * determines the maximum offset a back-reference can take. Must
+     * be a power of two.
+     * @throws IllegalArgumentException if windowSize is not a power of two.
      */
-    public Parameters(int windowSize) {
-        this(windowSize, TRUE_MIN_MATCH_LENGTH, windowSize - 1, windowSize - 1, windowSize);
+    public static Builder builder(int windowSize) {
+        return new Builder(windowSize);
     }
 
     /**
-     * Initializes the compressor's parameters.
-     *
-     * @param windowSize the size of the sliding window, must be a
-     * power of two - this determines the maximum offset a
-     * back-reference can take.
-     * @param minMatchLength the minimal length of a match found. A
-     * true minimum of 3 is hard-coded inside of this implemention
-     * but bigger lengths can be configured.
-     * @param maxMatchLength maximal length of a match found. A value
-     * smaller than <code>minMatchLength</code> as well as values
-     * bigger than <code>windowSize - 1</code> are interpreted as
-     * <code>windowSize - 1</code>.
-     * @param maxOffset maximal offset of a back-reference. A
-     * non-positive value as well as values bigger than
-     * <code>windowSize - 1</code> are interpreted as <code>windowSize
-     * - 1</code>.
-     * @param maxLiteralLength maximal length of a literal
-     * block. Negative numbers and 0 as well as values bigger than
-     * <code>windowSize</code> are interpreted as
-     * <code>windowSize</code>.
-     * @throws IllegalArgumentException if <code>windowSize</code> is
-     * smaller than <code>minMatchLength</code> or not a power of two.
+     * Builder for {@link Parameters} instances.
      */
-    public Parameters(int windowSize, int minMatchLength, int maxMatchLength,
-                      int maxOffset, int maxLiteralLength) {
-        this.minMatchLength = Math.max(TRUE_MIN_MATCH_LENGTH, minMatchLength);
-        if (windowSize < this.minMatchLength) {
-            throw new IllegalArgumentException("windowSize must be at least as big as minMatchLength");
+    public static class Builder {
+        private final int windowSize;
+        private int minBackReferenceLength, maxBackReferenceLength, maxOffset, maxLiteralLength;
+
+        private Builder(int windowSize) {
+            if (windowSize < 2 || !isPowerOfTwo(windowSize)) {
+                throw new IllegalArgumentException("windowSize must be a power of two");
+            }
+            this.windowSize = windowSize;
+            minBackReferenceLength = TRUE_MIN_BACK_REFERENCE_LENGTH;
+            maxBackReferenceLength = windowSize - 1;
+            maxOffset = windowSize - 1;
+            maxLiteralLength = windowSize;
         }
-        if (!isPowerOfTwo(windowSize)) {
-            throw new IllegalArgumentException("windowSize must be a power of two");
+
+        /**
+         * Sets the mininal length of a back-reference.
+         *
+         * <p>Ensures <code>maxBackReferenceLength</code> is not
+         * smaller than <code>minBackReferenceLength</code>.
+         *
+         * <p>It is recommended to not use this method directly but
+         * rather tune a pre-configured builder created by a format
+         * specific factory like {@link
+         * org.apache.commons.compress.compressors.snappy.SnappyCompressorOutputStream#createParameterBuilder}.</p>
+         *
+         * @param minBackReferenceLength the minimal length of a back-reference found. A
+         * true minimum of 3 is hard-coded inside of this implemention
+         * but bigger lengths can be configured.
+         * @throws IllegalArgumentException if <code>windowSize</code>
+         * is smaller than <code>minBackReferenceLength</code>.
+         */
+        public Builder withMinBackReferenceLength(int minBackReferenceLength) {
+            this.minBackReferenceLength = Math.max(TRUE_MIN_BACK_REFERENCE_LENGTH, minBackReferenceLength);
+            if (windowSize < this.minBackReferenceLength) {
+                throw new IllegalArgumentException("minBackReferenceLength can't be bigger than windowSize");
+            }
+            if (maxBackReferenceLength < this.minBackReferenceLength) {
+                maxBackReferenceLength = this.minBackReferenceLength;
+            }
+            return this;
+        }
+
+        /**
+         * Sets the maximal length of a back-reference.
+         *
+         * <p>It is recommended to not use this method directly but
+         * rather tune a pre-configured builder created by a format
+         * specific factory like {@link
+         * org.apache.commons.compress.compressors.snappy.SnappyCompressorOutputStream#createParameterBuilder}.</p>
+         *
+         * @param maxBackReferenceLength maximal length of a
+         * back-reference found. A value smaller than
+         * <code>minBackReferenceLength</code> is interpreted as
+         * <code>minBackReferenceLength</code>. <code>maxBackReferenceLength</code>
+         * is capped at <code>windowSize - 1</code>.
+         */
+        public Builder withMaxBackReferenceLength(int maxBackReferenceLength) {
+            this.maxBackReferenceLength = maxBackReferenceLength < minBackReferenceLength ? minBackReferenceLength
+                : Math.min(maxBackReferenceLength, windowSize - 1);
+            return this;
         }
+
+        /**
+         * Sets the maximal offset of a back-reference.
+         *
+         * <p>It is recommended to not use this method directly but
+         * rather tune a pre-configured builder created by a format
+         * specific factory like {@link
+         * org.apache.commons.compress.compressors.snappy.SnappyCompressorOutputStream#createParameterBuilder}.</p>
+         *
+         * @param maxOffset maximal offset of a back-reference. A
+         * non-positive value as well as values bigger than
+         * <code>windowSize - 1</code> are interpreted as <code>windowSize
+         * - 1</code>.
+         */
+        public Builder withMaxOffset(int maxOffset) {
+            this.maxOffset = maxOffset < 1 ? windowSize - 1 : Math.min(maxOffset, windowSize - 1);
+            return this;
+        }
+
+        /**
+         * Sets the maximal length of a literal block.
+         *
+         * <p>It is recommended to not use this method directly but
+         * rather tune a pre-configured builder created by a format
+         * specific factory like {@link
+         * org.apache.commons.compress.compressors.snappy.SnappyCompressorOutputStream#createParameterBuilder}.</p>
+         *
+         * @param maxLiteralLength maximal length of a literal
+         * block. Negative numbers and 0 as well as values bigger than
+         * <code>windowSize</code> are interpreted as
+         * <code>windowSize</code>.
+         */
+        public Builder withMaxLiteralLength(int maxLiteralLength) {
+            this.maxLiteralLength = maxLiteralLength < 1 ? windowSize
+                : Math.min(maxLiteralLength, windowSize);
+            return this;
+        }
+
+        /**
+         * Creates the {@link Parameters} instance.
+         * @return the configured {@link Parameters} instance.
+         */
+        public Parameters build() {
+            return new Parameters(windowSize, minBackReferenceLength, maxBackReferenceLength,
+                maxOffset, maxLiteralLength);
+        }
+    }
+
+    private final int windowSize, minBackReferenceLength, maxBackReferenceLength, maxOffset, maxLiteralLength;
+
+    private Parameters(int windowSize, int minBackReferenceLength, int maxBackReferenceLength, int maxOffset,
+        int maxLiteralLength) {
         this.windowSize = windowSize;
-        int limit = windowSize - 1;
-        this.maxOffset = maxOffset < 1 ? limit : Math.min(maxOffset, limit);
-        this.maxMatchLength = maxMatchLength < this.minMatchLength ? limit
-            : Math.min(maxMatchLength, limit);
-        this.maxLiteralLength = maxLiteralLength < 1 ? windowSize
-            : Math.min(maxLiteralLength, windowSize);
+        this.minBackReferenceLength = minBackReferenceLength;
+        this.maxBackReferenceLength = maxBackReferenceLength;
+        this.maxOffset = maxOffset;
+        this.maxLiteralLength = maxLiteralLength;
     }
 
     /**
@@ -90,22 +179,22 @@ public final class Parameters {
         return windowSize;
     }
     /**
-     * Gets the minimal length of a match found.
-     * @return the minimal length of a match found
+     * Gets the minimal length of a back-reference found.
+     * @return the minimal length of a back-reference found
      */
-    public int getMinMatchLength() {
-        return minMatchLength;
+    public int getMinBackReferenceLength() {
+        return minBackReferenceLength;
     }
     /**
-     * Gets the maximal length of a match found.
-     * @return the maximal length of a match found
+     * Gets the maximal length of a back-reference found.
+     * @return the maximal length of a back-reference found
      */
-    public int getMaxMatchLength() {
-        return maxMatchLength;
+    public int getMaxBackReferenceLength() {
+        return maxBackReferenceLength;
     }
     /**
-     * Gets the maximal offset of a match found.
-     * @return the maximal offset of a match found
+     * Gets the maximal offset of a back-reference found.
+     * @return the maximal offset of a back-reference found
      */
     public int getMaxOffset() {
         return maxOffset;

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorOutputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorOutputStream.java b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorOutputStream.java
index 8827aeb..3643794 100644
--- a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorOutputStream.java
@@ -82,7 +82,7 @@ public class SnappyCompressorOutputStream extends CompressorOutputStream {
      */
     public SnappyCompressorOutputStream(final OutputStream os, final long uncompressedSize, final int blockSize)
         throws IOException {
-        this(os, uncompressedSize, createParams(blockSize));
+        this(os, uncompressedSize, createParameterBuilder(blockSize).build());
     }
 
     /**
@@ -262,11 +262,18 @@ public class SnappyCompressorOutputStream extends CompressorOutputStream {
     // Snappy stores the match length in six bits of the tag
     private static final int MAX_MATCH_LENGTH = 64;
 
-    // package private for tests
-    static Parameters createParams(int blockSize) {
+    /**
+     * Returns a builder correctly configured for the Snappy algorithm using the gven block size.
+     * @param blockSize the block size.
+     */
+    public static Parameters.Builder createParameterBuilder(int blockSize) {
         // the max offset and max literal length defined by the format
         // are 2^32 - 1 and 2^32 respectively - with blockSize being
         // an integer we will never exceed that
-        return new Parameters(blockSize, MIN_MATCH_LENGTH, MAX_MATCH_LENGTH, blockSize, blockSize);
+        return Parameters.builder(blockSize)
+            .withMinBackReferenceLength(MIN_MATCH_LENGTH)
+            .withMaxBackReferenceLength(MAX_MATCH_LENGTH)
+            .withMaxOffset(blockSize)
+            .withMaxLiteralLength(blockSize);
     }
 }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/test/java/org/apache/commons/compress/compressors/lz77support/LZ77CompressorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/compressors/lz77support/LZ77CompressorTest.java b/src/test/java/org/apache/commons/compress/compressors/lz77support/LZ77CompressorTest.java
index ff925aa..9ac0c14 100644
--- a/src/test/java/org/apache/commons/compress/compressors/lz77support/LZ77CompressorTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/lz77support/LZ77CompressorTest.java
@@ -92,14 +92,14 @@ public class LZ77CompressorTest {
 
     @Test
     public void nonCompressableWithLengthSmallerThanLiteralMax() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(128), ONE_TO_TEN);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(128), ONE_TO_TEN);
         assertSize(2, blocks);
         assertLiteralBlock(ONE_TO_TEN, blocks.get(0));
     }
 
     @Test
     public void nonCompressableWithLengthGreaterThanLiteralMaxButLessThanTwiceWindowSize() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(8), ONE_TO_TEN);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(8), ONE_TO_TEN);
         assertSize(3, blocks);
         assertLiteralBlock(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, blocks.get(0));
         assertLiteralBlock(new byte[] { 9, 10 }, blocks.get(1));
@@ -107,7 +107,7 @@ public class LZ77CompressorTest {
 
     @Test
     public void nonCompressableWithLengthThatForcesWindowSlide() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(4), ONE_TO_TEN);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(4), ONE_TO_TEN);
         assertSize(4, blocks);
         assertLiteralBlock(new byte[] { 1, 2, 3, 4, }, blocks.get(0));
         assertLiteralBlock(new byte[] { 5, 6, 7, 8 }, blocks.get(1));
@@ -116,7 +116,7 @@ public class LZ77CompressorTest {
 
     @Test
     public void nonCompressableSentAsSingleBytes() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(8), stagger(ONE_TO_TEN));
+        List<LZ77Compressor.Block> blocks = compress(newParameters(8), stagger(ONE_TO_TEN));
         assertSize(3, blocks);
         assertLiteralBlock(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, blocks.get(0));
         assertLiteralBlock(new byte[] { 9, 10 }, blocks.get(1));
@@ -125,7 +125,7 @@ public class LZ77CompressorTest {
     @Test
     public void blaExampleWithFullArrayAvailableForCompression()
         throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(128), BLA);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(128), BLA);
         assertSize(4, blocks);
         assertLiteralBlock("Blah b", blocks.get(0));
         assertBackReference(5, 18, blocks.get(1));
@@ -133,8 +133,8 @@ public class LZ77CompressorTest {
     }
 
     @Test
-    public void blaExampleWithShorterMatchLength() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(128, 3, 5, 0, 0), BLA);
+    public void blaExampleWithShorterBackReferenceLength() throws IOException {
+        List<LZ77Compressor.Block> blocks = compress(newParameters(128, 3, 5, 0, 0), BLA);
         assertSize(7, blocks);
         assertLiteralBlock("Blah b", blocks.get(0));
         assertBackReference(5, 5, blocks.get(1));
@@ -146,7 +146,7 @@ public class LZ77CompressorTest {
 
     @Test
     public void blaExampleSmallerWindowSize() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(8), BLA);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(8), BLA);
         assertSize(6, blocks);
         assertLiteralBlock("Blah b", blocks.get(0));
         assertEquals(LZ77Compressor.BackReference.class, blocks.get(1).getClass());
@@ -158,7 +158,7 @@ public class LZ77CompressorTest {
 
     @Test
     public void blaExampleWithSingleByteWrites() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(128), stagger(BLA));
+        List<LZ77Compressor.Block> blocks = compress(newParameters(128), stagger(BLA));
         assertEquals(9, blocks.size());
         assertLiteralBlock("Blah b", blocks.get(0));
         assertBackReference(5, 3, blocks.get(1));
@@ -172,7 +172,7 @@ public class LZ77CompressorTest {
 
     @Test
     public void samIAmExampleWithFullArrayAvailableForCompression() throws IOException {
-        List<LZ77Compressor.Block> blocks = compress(new Parameters(1024), SAM);
+        List<LZ77Compressor.Block> blocks = compress(newParameters(1024), SAM);
         assertEquals(21, blocks.size());
         assertLiteralBlock("I am Sam\n\n", blocks.get(0));
         assertBackReference(5, 3, blocks.get(1));
@@ -199,7 +199,7 @@ public class LZ77CompressorTest {
     @Test
     public void blaExampleWithPrefill() throws IOException {
         final List<LZ77Compressor.Block> blocks = new ArrayList<>();
-        LZ77Compressor c = new LZ77Compressor(new Parameters(128), new LZ77Compressor.Callback() {
+        LZ77Compressor c = new LZ77Compressor(newParameters(128), new LZ77Compressor.Callback() {
                 @Override
                 public void accept(LZ77Compressor.Block block) {
                     //System.err.println(block);
@@ -227,7 +227,7 @@ public class LZ77CompressorTest {
     @Test
     public void blaExampleWithShortPrefill() throws IOException {
         final List<LZ77Compressor.Block> blocks = new ArrayList<>();
-        LZ77Compressor c = new LZ77Compressor(new Parameters(128), new LZ77Compressor.Callback() {
+        LZ77Compressor c = new LZ77Compressor(newParameters(128), new LZ77Compressor.Callback() {
                 @Override
                 public void accept(LZ77Compressor.Block block) {
                     //System.err.println(block);
@@ -256,7 +256,7 @@ public class LZ77CompressorTest {
     @Test
     public void blaExampleWithPrefillBiggerThanWindowSize() throws IOException {
         final List<LZ77Compressor.Block> blocks = new ArrayList<>();
-        LZ77Compressor c = new LZ77Compressor(new Parameters(4), new LZ77Compressor.Callback() {
+        LZ77Compressor c = new LZ77Compressor(newParameters(4), new LZ77Compressor.Callback() {
                 @Override
                 public void accept(LZ77Compressor.Block block) {
                     //System.err.println(block);
@@ -286,7 +286,7 @@ public class LZ77CompressorTest {
 
     @Test(expected = IllegalStateException.class)
     public void cantPrefillTwice() {
-        LZ77Compressor c = new LZ77Compressor(new Parameters(128), new LZ77Compressor.Callback() {
+        LZ77Compressor c = new LZ77Compressor(newParameters(128), new LZ77Compressor.Callback() {
                 @Override
                 public void accept(LZ77Compressor.Block block) {
                 }
@@ -297,7 +297,7 @@ public class LZ77CompressorTest {
 
     @Test(expected = IllegalStateException.class)
     public void cantPrefillAfterCompress() throws IOException {
-        LZ77Compressor c = new LZ77Compressor(new Parameters(128), new LZ77Compressor.Callback() {
+        LZ77Compressor c = new LZ77Compressor(newParameters(128), new LZ77Compressor.Callback() {
                 @Override
                 public void accept(LZ77Compressor.Block block) {
                 }
@@ -335,4 +335,18 @@ public class LZ77CompressorTest {
         }
         return r;
     }
+
+    private static Parameters newParameters(int windowSize) {
+        return Parameters.builder(windowSize).build();
+    }
+
+    private static Parameters newParameters(int windowSize, int minBackReferenceLength, int maxBackReferenceLength,
+        int maxOffset, int maxLiteralLength) {
+        return Parameters.builder(windowSize)
+            .withMinBackReferenceLength(minBackReferenceLength)
+            .withMaxBackReferenceLength(maxBackReferenceLength)
+            .withMaxOffset(maxOffset)
+            .withMaxLiteralLength(maxLiteralLength)
+            .build();
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/test/java/org/apache/commons/compress/compressors/lz77support/ParametersTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/compressors/lz77support/ParametersTest.java b/src/test/java/org/apache/commons/compress/compressors/lz77support/ParametersTest.java
index 22e5bdf..2597462 100644
--- a/src/test/java/org/apache/commons/compress/compressors/lz77support/ParametersTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/lz77support/ParametersTest.java
@@ -26,85 +26,110 @@ public class ParametersTest {
 
     @Test
     public void defaultConstructor() {
-        Parameters p = new Parameters(128);
+        Parameters p = newParameters(128);
         assertEquals(128, p.getWindowSize());
-        assertEquals(3, p.getMinMatchLength());
-        assertEquals(127, p.getMaxMatchLength());
+        assertEquals(3, p.getMinBackReferenceLength());
+        assertEquals(127, p.getMaxBackReferenceLength());
         assertEquals(127, p.getMaxOffset());
         assertEquals(128, p.getMaxLiteralLength());
     }
 
     @Test
-    public void minMatchLengthIsAtLeastThree() {
-        Parameters p = new Parameters(128, 2, 3, 4, 5);
-        assertEquals(3, p.getMinMatchLength());
+    public void minBackReferenceLengthIsAtLeastThree() {
+        Parameters p = newParameters(128, 2, 3, 4, 5);
+        assertEquals(3, p.getMinBackReferenceLength());
     }
 
     @Test
-    public void maxMatchLengthIsWinsizeMinus1WhenSmallerThanMinMatchLength() {
-        Parameters p = new Parameters(128, 2, 2, 4, 5);
-        assertEquals(127, p.getMaxMatchLength());
+    public void maxBackReferenceLengthIsMinBackReferenceLengthWhenSmallerThanMinBackReferenceLength() {
+        Parameters p = newParameters(128, 2, 2, 4, 5);
+        assertEquals(3, p.getMaxBackReferenceLength());
     }
 
     @Test
-    public void maxMatchLengthIsMinMatchLengthIfBothAreEqual() {
-        Parameters p = new Parameters(128, 2, 3, 4, 5);
-        assertEquals(3, p.getMaxMatchLength());
+    public void maxBackReferenceLengthIsMinBackReferenceLengthWhenSmallerThanMinBackReferenceLengthReversedInvocationOrder() {
+        Parameters p = Parameters.builder(128)
+            .withMaxBackReferenceLength(2)
+            .withMinBackReferenceLength(2)
+            .withMaxOffset(4)
+            .withMaxLiteralLength(5)
+            .build();
+        assertEquals(3, p.getMaxBackReferenceLength());
+    }
+
+    @Test
+    public void maxBackReferenceLengthIsMinBackReferenceLengthIfBothAreEqual() {
+        Parameters p = newParameters(128, 2, 3, 4, 5);
+        assertEquals(3, p.getMaxBackReferenceLength());
     }
 
     @Test
     public void maxOffsetIsWindowSizeMinus1IfSetTo0() {
-        Parameters p = new Parameters(128, 2, 3, 0, 5);
+        Parameters p = newParameters(128, 2, 3, 0, 5);
         assertEquals(127, p.getMaxOffset());
     }
 
     @Test
     public void maxOffsetIsWindowSizeMinus1IfSetToANegativeValue() {
-        Parameters p = new Parameters(128, 2, 3, -1, 5);
+        Parameters p = newParameters(128, 2, 3, -1, 5);
         assertEquals(127, p.getMaxOffset());
     }
 
     @Test
     public void maxOffsetIsWindowSizeMinus1IfBiggerThanWindowSize() {
-        Parameters p = new Parameters(128, 2, 3, 129, 5);
+        Parameters p = newParameters(128, 2, 3, 129, 5);
         assertEquals(127, p.getMaxOffset());
     }
 
     @Test
     public void maxLiteralLengthIsWindowSizeIfSetTo0() {
-        Parameters p = new Parameters(128, 2, 3, 4, 0);
+        Parameters p = newParameters(128, 2, 3, 4, 0);
         assertEquals(128, p.getMaxLiteralLength());
     }
 
     @Test
     public void maxLiteralLengthIsWindowSizeIfSetToANegativeValue() {
-        Parameters p = new Parameters(128, 2, 3, 0, -1);
+        Parameters p = newParameters(128, 2, 3, 0, -1);
         assertEquals(128, p.getMaxLiteralLength());
     }
 
     @Test
     public void maxLiteralLengthIsWindowSizeIfSetToAValueTooBigToHoldInSlidingWindow() {
-        Parameters p = new Parameters(128, 2, 3, 0, 259);
+        Parameters p = newParameters(128, 2, 3, 0, 259);
         assertEquals(128, p.getMaxLiteralLength());
     }
 
     @Test
     public void allParametersUsuallyTakeTheirSpecifiedValues() {
-        Parameters p = new Parameters(256, 4, 5, 6, 7);
+        Parameters p = newParameters(256, 4, 5, 6, 7);
         assertEquals(256, p.getWindowSize());
-        assertEquals(4, p.getMinMatchLength());
-        assertEquals(5, p.getMaxMatchLength());
+        assertEquals(4, p.getMinBackReferenceLength());
+        assertEquals(5, p.getMaxBackReferenceLength());
         assertEquals(6, p.getMaxOffset());
         assertEquals(7, p.getMaxLiteralLength());
     }
 
     @Test(expected = IllegalArgumentException.class)
-    public void windowSizeMustNotBeSmallerThanMinMatchLength() {
-        new Parameters(128, 200, 300, 400, 500);
+    public void windowSizeMustNotBeSmallerThanMinBackReferenceLength() {
+        newParameters(128, 200, 300, 400, 500);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void windowSizeMustNotBeAPowerOfTwo() {
-        new Parameters(100, 200, 300, 400, 500);
+        newParameters(100, 200, 300, 400, 500);
+    }
+
+    private static Parameters newParameters(int windowSize) {
+        return Parameters.builder(windowSize).build();
+    }
+
+    private static Parameters newParameters(int windowSize, int minBackReferenceLength, int maxBackReferenceLength,
+        int maxOffset, int maxLiteralLength) {
+        return Parameters.builder(windowSize)
+            .withMinBackReferenceLength(minBackReferenceLength)
+            .withMaxBackReferenceLength(maxBackReferenceLength)
+            .withMaxOffset(maxOffset)
+            .withMaxLiteralLength(maxLiteralLength)
+            .build();
     }
 }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5170392a/src/test/java/org/apache/commons/compress/compressors/snappy/SnappyRoundtripTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/compressors/snappy/SnappyRoundtripTest.java b/src/test/java/org/apache/commons/compress/compressors/snappy/SnappyRoundtripTest.java
index 481d07c..427c8d0 100644
--- a/src/test/java/org/apache/commons/compress/compressors/snappy/SnappyRoundtripTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/snappy/SnappyRoundtripTest.java
@@ -33,7 +33,8 @@ public final class SnappyRoundtripTest extends AbstractTestCase {
 
     private void roundTripTest(String testFile) throws IOException {
         roundTripTest(getFile(testFile),
-            SnappyCompressorOutputStream.createParams(SnappyCompressorInputStream.DEFAULT_BLOCK_SIZE));
+            SnappyCompressorOutputStream.createParameterBuilder(SnappyCompressorInputStream.DEFAULT_BLOCK_SIZE)
+                .build());
     }
 
     private void roundTripTest(final File input, Parameters params) throws IOException {
@@ -102,7 +103,7 @@ public final class SnappyRoundtripTest extends AbstractTestCase {
             fs.write(0);
             fs.write(0);
         }
-        roundTripTest(f, new Parameters(1 << 17, 4, 64, 1 << 17 - 1, 1 << 17 - 1));
+        roundTripTest(f, newParameters(1 << 17, 4, 64, 1 << 17 - 1, 1 << 17 - 1));
     }
 
     @Test
@@ -128,7 +129,16 @@ public final class SnappyRoundtripTest extends AbstractTestCase {
                 fs.write(r.nextInt(256));
             }
         }
-        roundTripTest(f, new Parameters(1 << 18, 4, 64, 1 << 16 - 1, 1 << 18 - 1));
+        roundTripTest(f, newParameters(1 << 18, 4, 64, 1 << 16 - 1, 1 << 18 - 1));
     }
 
+    private static Parameters newParameters(int windowSize, int minBackReferenceLength, int maxBackReferenceLength,
+        int maxOffset, int maxLiteralLength) {
+        return Parameters.builder(windowSize)
+            .withMinBackReferenceLength(minBackReferenceLength)
+            .withMaxBackReferenceLength(maxBackReferenceLength)
+            .withMaxOffset(maxOffset)
+            .withMaxLiteralLength(maxLiteralLength)
+            .build();
+    }
 }