class JoinUsing extends JoinCriteria {

    private static QualifiedName extendQualifiedName(QualifiedName name, String ext) {
        List<String> parts = new ArrayList<>(name.getParts().size() + 1);
        parts.addAll(name.getParts());
        parts.add(ext);
        return new QualifiedName(parts);
    }

    public static Expression toExpression(QualifiedName left, QualifiedName right, List<String> columns) {
        if (columns.isEmpty()) {
            throw new IllegalArgumentException("columns must not be empty");
        }
        List<ComparisonExpression> comp = columns.stream()
            .map(col -> new ComparisonExpression(
                ComparisonExpression.Type.EQUAL,
                new QualifiedNameReference(extendQualifiedName(left, col)),
                new QualifiedNameReference((extendQualifiedName(right, col)))))
            .toList();
        if (1 == comp.size()) {
            return comp.get(0);
        }
        Expression expr = null;
        for (int i = comp.size() - 2; i >= 0; i--) {
            if (null == expr) {
                expr = new LogicalBinaryExpression(
                    LogicalBinaryExpression.Type.AND,
                    comp.get(i),
                    comp.get(i + 1));
            } else {
                expr = new LogicalBinaryExpression(
                    LogicalBinaryExpression.Type.AND,
                    comp.get(i),
                    expr);
            }
        }
        return expr;
    }


    private final List<String> columns;

    public JoinUsing(List<String> columns) {
        if (columns.isEmpty()) {
            throw new IllegalArgumentException("columns must not be empty");
        }
        this.columns = List.copyOf(columns);
    }

    public List<String> getColumns() {
        return columns;
    }

    @Override
    public boolean equals(Object o) {<FILL_FUNCTION_BODY>}

    @Override
    public int hashCode() {
        return Objects.hash(columns);
    }

    @Override
    public String toString() {
        return "JoinUsing{" +
               "columns=" + columns +
               '}';
    }
}

        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        JoinUsing joinUsing = (JoinUsing) o;
        return Objects.equals(columns, joinUsing.columns);
    
<methods>public non-sealed void <init>() ,public abstract boolean equals(java.lang.Object) ,public abstract int hashCode() ,public abstract java.lang.String toString() <variables>