public List<KeyValue> generateTestKeyValues(int howMany, boolean useTags) {
    List<KeyValue> result = new ArrayList<>();

    List<byte[]> rows = generateRows();
    Map<Integer, List<byte[]>> rowsToQualifier = new HashMap<>();

    if (family == null) {
      family = new byte[columnFamilyLength];
      randomizer.nextBytes(family);
    }

    long baseTimestamp = randomizer.nextInt(Integer.MAX_VALUE) / baseTimestampDivide;

    byte[] value = new byte[valueLength];

    for (int i = 0; i < howMany; ++i) {
      long timestamp = baseTimestamp;
      if (timestampDiffSize > 0) {
        timestamp += randomizer.nextInt(timestampDiffSize);
      }
      Integer rowId = randomizer.nextInt(rows.size());
      byte[] row = rows.get(rowId);

      // generate qualifier, sometimes it is same, sometimes similar,
      // occasionally completely different
      byte[] qualifier;
      float qualifierChance = randomizer.nextFloat();
      if (
        !rowsToQualifier.containsKey(rowId)
          || qualifierChance > chanceForSameQualifier + chanceForSimilarQualifier
      ) {
        int qualifierLength = averageQualifierLength;
        qualifierLength +=
          randomizer.nextInt(2 * qualifierLengthVariance + 1) - qualifierLengthVariance;
        qualifier = new byte[qualifierLength];
        randomizer.nextBytes(qualifier);

        // add it to map
        if (!rowsToQualifier.containsKey(rowId)) {
          rowsToQualifier.put(rowId, new ArrayList<>());
        }
        rowsToQualifier.get(rowId).add(qualifier);
      } else if (qualifierChance > chanceForSameQualifier) {
        // similar qualifier
        List<byte[]> previousQualifiers = rowsToQualifier.get(rowId);
        byte[] originalQualifier =
          previousQualifiers.get(randomizer.nextInt(previousQualifiers.size()));

        qualifier = new byte[originalQualifier.length];
        int commonPrefix = randomizer.nextInt(qualifier.length);
        System.arraycopy(originalQualifier, 0, qualifier, 0, commonPrefix);
        for (int j = commonPrefix; j < qualifier.length; ++j) {
          qualifier[j] = (byte) (randomizer.nextInt() & 0xff);
        }

        rowsToQualifier.get(rowId).add(qualifier);
      } else {
        // same qualifier
        List<byte[]> previousQualifiers = rowsToQualifier.get(rowId);
        qualifier = previousQualifiers.get(randomizer.nextInt(previousQualifiers.size()));
      }

      if (randomizer.nextFloat() < chanceForZeroValue) {
        Arrays.fill(value, (byte) 0);
      } else {
        randomizer.nextBytes(value);
      }

      if (useTags) {
        result.add(new KeyValue(row, family, qualifier, timestamp, value,
          new Tag[] { new ArrayBackedTag((byte) 1, "value1") }));
      } else {
        result.add(new KeyValue(row, family, qualifier, timestamp, value));
      }
    }

    result.sort(CellComparator.getInstance());

    return result;
  }
Generate test data useful to test encoders.
@param howMany How many Key values should be generated.
@return sorted list of key values
hbase-common/src/test/java/org/apache/hadoop/hbase/util/RedundantKVGenerator.java