public static InRawPredicateEvaluator newRawValueBasedEvaluator(InPredicate inPredicate, DataType dataType) {
    switch (dataType) {
      case INT: {
        int[] intValues = inPredicate.getIntValues();
        IntSet matchingValues = new IntOpenHashSet(HashUtil.getMinHashSetSize(intValues.length));
        for (int value : intValues) {
          matchingValues.add(value);
        }
        return new IntRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case LONG: {
        long[] longValues = inPredicate.getLongValues();
        LongSet matchingValues = new LongOpenHashSet(HashUtil.getMinHashSetSize(longValues.length));
        for (long value : longValues) {
          matchingValues.add(value);
        }
        return new LongRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case FLOAT: {
        float[] floatValues = inPredicate.getFloatValues();
        FloatSet matchingValues = new FloatOpenHashSet(HashUtil.getMinHashSetSize(floatValues.length));
        for (float value : floatValues) {
          matchingValues.add(value);
        }
        return new FloatRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case DOUBLE: {
        double[] doubleValues = inPredicate.getDoubleValues();
        DoubleSet matchingValues = new DoubleOpenHashSet(HashUtil.getMinHashSetSize(doubleValues.length));
        for (double value : doubleValues) {
          matchingValues.add(value);
        }
        return new DoubleRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case BIG_DECIMAL: {
        BigDecimal[] bigDecimalValues = inPredicate.getBigDecimalValues();
        // NOTE: Use TreeSet because BigDecimal's compareTo() is not consistent with equals()
        //       E.g. compareTo(3.0, 3) returns 0 but equals(3.0, 3) returns false
        TreeSet<BigDecimal> matchingValues = new TreeSet<>(Arrays.asList(bigDecimalValues));
        return new BigDecimalRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case BOOLEAN: {
        int[] booleanValues = inPredicate.getBooleanValues();
        IntSet matchingValues = new IntOpenHashSet(HashUtil.getMinHashSetSize(booleanValues.length));
        for (int value : booleanValues) {
          matchingValues.add(value);
        }
        return new IntRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case TIMESTAMP: {
        long[] timestampValues = inPredicate.getTimestampValues();
        LongSet matchingValues = new LongOpenHashSet(HashUtil.getMinHashSetSize(timestampValues.length));
        for (long value : timestampValues) {
          matchingValues.add(value);
        }
        return new LongRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case STRING:
      case JSON: {
        List<String> stringValues = inPredicate.getValues();
        Set<String> matchingValues = new ObjectOpenHashSet<>(HashUtil.getMinHashSetSize(stringValues.size()));
        // NOTE: Add value-by-value to avoid overhead
        for (String value : stringValues) {
          //noinspection UseBulkOperation
          matchingValues.add(value);
        }
        return new StringRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      case BYTES: {
        ByteArray[] bytesValues = inPredicate.getBytesValues();
        Set<ByteArray> matchingValues = new ObjectOpenHashSet<>(HashUtil.getMinHashSetSize(bytesValues.length));
        // NOTE: Add value-by-value to avoid overhead
        //noinspection ManualArrayToCollectionCopy
        for (ByteArray value : bytesValues) {
          //noinspection UseBulkOperation
          matchingValues.add(value);
        }
        return new BytesRawValueBasedInPredicateEvaluator(inPredicate, matchingValues);
      }
      default:
        throw new IllegalStateException("Unsupported data type: " + dataType);
    }
  }
@Test
  void canBeVisited() {
    // Given a visitor
    MultiValueVisitor<Integer> valueLengthVisitor = Mockito.spy(createValueLengthVisitor());

    // When int predicate is used
    InPredicate predicate = new InPredicate(ExpressionContext.forIdentifier("ident"), Lists.newArrayList("1", "2"));

    InPredicateEvaluatorFactory.InRawPredicateEvaluator intEvaluator =
        InPredicateEvaluatorFactory.newRawValueBasedEvaluator(predicate, FieldSpec.DataType.INT);

    // Only the int[] method is called
    int length = intEvaluator.accept(valueLengthVisitor);
    Assert.assertEquals(length, 2);
    Mockito.verify(valueLengthVisitor).visitInt(new int[] {2, 1});
    Mockito.verifyNoMoreInteractions(valueLengthVisitor);

    // And given a string predicate
    InPredicateEvaluatorFactory.InRawPredicateEvaluator strEvaluator =
        InPredicateEvaluatorFactory.newRawValueBasedEvaluator(predicate, FieldSpec.DataType.STRING);

    // Only the string[] method is called
    length = strEvaluator.accept(valueLengthVisitor);
    Assert.assertEquals(length, 2);
    Mockito.verify(valueLengthVisitor).visitString(new String[] {"2", "1"});
    Mockito.verifyNoMoreInteractions(valueLengthVisitor);
  }