Hbase java API与过滤器

一、Hbase java API:

1、创建一张表
2、删除一张表
3、向一张表中添加一条数据
4、向一张表中同时添加一批数据
5、获取一条数据
6、获取一批数据
7、创建预分region表

代码实现:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;


/*
    java操作数据的步骤:
    1、注册驱动
    2、创建数据库连接对象
    3、创建数据库操作对象
    4、进行增删改查
    5、如果时查询的话,可以对查询的结果进行分析
    6、释放资源


    hbase基础中要做的需求:
        1、如何创建一张表
        2、如何删除一张表
        3、如何向一张表中添加一条数据
        4、如何向一张表中同时添加一批数据
        5、如何获取一条数据
        6、如果获取一批数据
        7、如何创建预分region表

 */
public class HBaseAPI {
    private Connection conn;
    private Admin admin;

    /**
     * 在所有Test方法执行之前执行
     */
    @Before
    public void getConnection() {
        try {
            //1、获取hbase集群的配置文件对象
            //0.90.0之前旧版本的写法:
//        HBaseConfiguration conf = new HBaseConfiguration();
            //新版本的写法:调用静态方法public static Configuration create()
            Configuration conf = HBaseConfiguration.create();

            Properties prop = new Properties();
            prop.load(new BufferedReader(new FileReader("src/main/resources/hbase.properties")));

            String zk = (String)prop.get("hbase.zookeeper.quorum");

            //2、因为hbase的数据都有一条元数据,而元数据也存储在一张表中,这张元数据表也有元数据,存储在zookeeper中
            //配置文件要设置你自己的zookeeper集群
            conf.set("hbase.zookeeper.quorum",zk); //前提时windows中配置了hosts映射

            //3、获取数据库的连接对象
            conn = ConnectionFactory.createConnection(conf);

            //4、获取数据库操作对象
//            HBaseAdmin hBaseAdmin = new HBaseAdmin(conn);
            //新版本的做法
            admin = conn.getAdmin(); //使用连接对象获取数据库操作对象
            System.out.println("数据库连接对象获取成功!!" + conn);
            System.out.println("数据库操作对象获取成功!!" + admin);
            System.out.println("==========================================");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 需求1:  1、如何创建一张表
     * create 'students','info'  必须要有表名和列簇的名
     */
    @Test
    public void createOneTable() {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf("students2");
            //HTableDescriptor类已经在2.0.0版本之后就过时了,并且在3.0.0之后完全被删除
            //新版本不能使用这个类
//        HTableDescriptor students = new HTableDescriptor(tn);
            //新版本使用 TableDescriptorBuilder 类来创建并获取表描述器对象
            //public static TableDescriptorBuilder newBuilder(final TableName name)
            TableDescriptorBuilder students = TableDescriptorBuilder.newBuilder(tn);

            //旧版本创建列簇描述器对象
//        HColumnDescriptor info = new HColumnDescriptor("info");
            //新版本中ColumnFamilyDescriptorBuilder.of(String).
            ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of("info");

            //将列簇与表进行关联
            //旧版本中表描述器调用addColumnFamily方法将列簇描述器添加到表中
//        students.addColumnFamily(info);
            //新版本中使用setColumnFamily
            students.setColumnFamily(info);

            //调用方法,创建表
            // createTable(TableDescriptor desc)
            //             TableDescriptorBuilder
            admin.createTable(students.build());
            System.out.println(tn + "表创建成功!!!");
        } catch (Exception e) {
            System.out.println("表创建失败!!");
            e.printStackTrace();
        }
    }

    /**
     * 需求:2、如何删除一张表
     * disable 'students'
     * drop 'students'
     */
    @Test
    public void dropOneTable() {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf("tb_split2");

            //判断表是否存在
            if (admin.tableExists(tn)) {
                //先禁用表
                admin.disableTable(tn);

                //使用admin对象调用方法删除表
                //void deleteTable(TableName tableName)
                admin.deleteTable(tn);

                System.out.println(tn + "表成功被删除");
            } else {
                System.out.println(tn + "表不存在!!");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 需求:3、如何向一张表中添加一条数据
     * put 'students','1001','info:name','小虎'
     */
    @Test
    public void putOneDataToTable() {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf("students");

            //判断表是否存在
            if (admin.tableExists(tn)) {
                //获取表对象
                Table students = conn.getTable(tn);
                //创建Put对象
//                Put put = new Put("1001".getBytes());//行键的字节数组形式
//                //对put对象进行设置,添加列簇,列名和列值
//                put.addColumn("info".getBytes(),"name".getBytes(),"小虎".getBytes());

                //hbase自带的一个工具类Bytes,可以将字符串转字节数组
                Put put = new Put(Bytes.toBytes("1001"));//行键的字节数组形式
                //对put对象进行设置,添加列簇,列名和列值  以前的写法
//                put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes("小虎"));
                //public Put add(Cell cell) 新版本另外一种设置put对象的方式
                //Cell 是一个接口,无法被实例化,使用实现类KeyValue来创建对象
                //KeyValue(final byte [] row, final byte [] family, final byte [] qualifier, final byte [] value)
                put.add(new KeyValue(Bytes.toBytes("1001"),
                        Bytes.toBytes("info"),
                        Bytes.toBytes("age"),
                        Bytes.toBytes(18)));

                //void put(Put put)
                //需要先将我们添加的列数据封装成一个Put对象
                students.put(put);

            } else {
                System.out.println(tn + "表不存在!!");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 需求:4、如何向一张表中同时添加一批数据
     */
    @Test
    public void putMoreDataToTable() {
        BufferedReader br = null;
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf("students2");
            //创建字符输入缓冲流
            br = new BufferedReader(new FileReader("data/students.csv"));

            String[] colNameArray = {"", "name", "age", "gender", "clazz"};

            //判断表是否存在
            if (admin.tableExists(tn)) {
                //获取表对象
                Table students = conn.getTable(tn);
                //循环读取数据
                String line = null;
                while ((line = br.readLine()) != null) {
                    String[] info = line.split(",");
                    byte[] rowKey = Bytes.toBytes(info[0]);
                    //创建这一行的Put对象
                    Put put = new Put(rowKey);
                    //第一列作为行键唯一标识,从第二列开始,每一列都要被封装成Put对象
                    for (int i = 1; i < info.length; i++) {
                        byte[] colName = Bytes.toBytes(info[i]);
                        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes(colNameArray[i]), Bytes.toBytes(info[i]));
                        //添加该列数据
                        students.put(put);
                    }
                }

                System.out.println("学生表数据添加完毕!!!!");
            } else {
                System.out.println(tn + "表不存在!!");
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 需求:5、如何获取一条数据
     * get 'students','1500101000'
     */
    @Test
    public void getOneData() {
        try {
            //将表名封装TableName对象
            TableName sd = TableName.valueOf("students");

            //获取表的对象
            Table students = conn.getTable(sd);

            //传入行键的字节数组的形式
            Get get = new Get(Bytes.toBytes("1500101000"));

            //default Result get(Get get)
            Result result = students.get(get);
//            System.out.println(result);
            /**
             *  Result类中的常用方法:
             *      getRow() : 获取行键的字节数组形式
             *      getValue(byte [] family, byte [] qualifier): 根据列簇和列名,获取列值的字节数组形式
             *      List<Cell> listCells():获取所有单元格,单元格中存储了行键,列簇,列名,版本号(时间戳),列值
             */
            String id = Bytes.toString(result.getRow());
            //在已经知道列名的前提之下获取对应的列值
//            String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
//            String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
//            String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
//            String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
//            System.out.println("学号:"+id+",姓名:"+name+",年龄:"+age+",性别:"+gender+",班级:"+clazz);
            //当不清楚列名的时候该如何获取呢?
            //获取一行中的所有单元格组合的集合
            List<Cell> cells = result.listCells(); //获取的结果值的顺序是hbase中存储排序后的顺序
            //遍历集合得到每个单元格,获取每个列值
            /**
             * hbase中除了提供一个Bytes工具类给我们使用以外,还提供了另外的一个工具类:CellUtil
             * 该工具类主要的操作对象是Cell类的对象
             */
            //遍历方式1:普通for循环遍历
            //遍历方式2:增强for循环遍历
//            for (Cell cell : cells) {
//                String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
//                String colValue = Bytes.toString(CellUtil.cloneValue(cell));
//                System.out.println(colName + ":" + colValue);
//            }
            //遍历方式3:forEach + lambda表达式
//            cells.forEach(e -> {
//                String colName = Bytes.toString(CellUtil.cloneQualifier(e));
//                String colValue = Bytes.toString(CellUtil.cloneValue(e));
//                System.out.println(colName + ":" + colValue);
//            });
            //遍历方式4:jdk1.8新特性遍历,转流处理
            cells.stream().map(e -> {
                String colName = Bytes.toString(CellUtil.cloneQualifier(e));
                String colValue = Bytes.toString(CellUtil.cloneValue(e));
//                System.out.println(colName + ":" + colValue);
                return colName + ":" + colValue;
            }).forEach(System.out::println);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 6、如果获取一批数据 第一种方式
     */
    @Test
    public void getMoreData() {
        try {
            //将表名封装TableName对象
            TableName sd = TableName.valueOf("students");

            //获取表的对象
            Table students = conn.getTable(sd);

            //创建List集合,存储多个Get对象
            //1500100001 ~ 1500101000
            ArrayList<Get> gets = new ArrayList<>();
            for (int i = 1500100001; i <= 1500101000; i++) {
                gets.add(new Get(Bytes.toBytes(String.valueOf(i))));
            }

            //default Result[] get(List<Get> gets)
            Result[] results = students.get(gets);
            //1、先遍历results得到每一个result(每一行)
            //2、遍历每一个result中的每一列
            for (Result result : results) {
                List<Cell> cells = result.listCells();
                if (cells != null) {
                    cells.stream().map(cell -> {
                        String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
                        String colValue = Bytes.toString(CellUtil.cloneValue(cell));
//                System.out.println(colName + ":" + colValue);
                        return colName + ":" + colValue;
                    }).forEach(System.out::println);
                    System.out.println("-----------------");
                } else {
                    System.out.println("是空");
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 7、如果获取一批数据 第二种方式
     * scan 'students' 默认情况下获取表所有数据
     * scan 'students',LIMIT=>3
     */
    @Test
    public void ScanData() {
        try {
            TableName sd = TableName.valueOf("students");
            Table students = conn.getTable(sd);
            //创建Scan对象
            Scan scan = new Scan(); //查询表中的所有行
            //设置开始行和结束行
            //旧版本写法
//            scan.setStartRow(Bytes.toBytes("1500100001"));
//            scan.setStopRow(Bytes.toBytes("1500100004"));
            //新版本写法
//            scan.withStartRow(Bytes.toBytes("1500100001"));
//            scan.withStopRow(Bytes.toBytes("1500100004"), true);

            //设置取前几行
            scan.setLimit(10);

            //default ResultScanner getScanner(Scan scan)
            ResultScanner resultScanner = students.getScanner(scan);
            //通过观察源码发现,可以先获取迭代器对象
            Iterator<Result> iterator = resultScanner.iterator();
            while (iterator.hasNext()) {
                Result result = iterator.next();
                //不知道列名的时候遍历
//                List<Cell> cells = result.listCells();
//                    cells.stream().map(cell->{
//                    String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
//                    String colValue = Bytes.toString(CellUtil.cloneValue(cell));
//                    return colName + ":" + colValue;
//                }).forEach(System.out::println);
                //知道列簇列名的时候遍历
//                String id = Bytes.toString(result.getRow());
                //在已经知道列名的前提之下获取对应的列值
//                String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
//                String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
//                String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
//                String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
//                System.out.println("学号:" + id + ",姓名:" + name + ",年龄:" + age + ",性别:" + gender + ",班级:" + clazz);
                printResult(result);
                System.out.println("-----------------");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 需求:7、如何创建预分region表
     * 将来对于某一个RegionServer而言,可能会接收大量的并发请求,超出了该RegionServer承受的压力,有可能会导致该子节点崩溃
     * 如果大量的并发请求查询的数据是多种多种多样的,只不过巧合的是都在一个RegionServer上管理
     * 解决的思路:分散查询的数据到不同的RegionServer上,这样请求也会随着被分散到不同的RegionServer上,就达到了减轻某一个RegionServer压力过大情况,解决了单点故障的问题
     */
    @Test
    public void createPreviewTable(){
        try {
            //先将表名封装成TableName对象
            TableName tb = TableName.valueOf("tb_split2");

            //创建表描述器对象
            TableDescriptorBuilder tbSplit2 = TableDescriptorBuilder.newBuilder(tb);

            //创建列簇描述器对象
            ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of("info");

            //将列簇添加到表中
            tbSplit2.setColumnFamily(info);

            //创建分割键的二维数组
            byte[][] splitKeys = {
                    Bytes.toBytes("f"),
                    Bytes.toBytes("k"),
                    Bytes.toBytes("p")
            };

            //调用方法创建表
//            admin.createTable(tbSplit2.build());
            //调用另外一个方法,传入表描述器的同时,传入分割点,创建预分region表
            //void createTable(TableDescriptor desc, byte[][] splitKeys)
            admin.createTable(tbSplit2.build(),splitKeys);
            System.out.println("预分region表创建成功!!!");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void printResult(Result result) {
        String id = Bytes.toString(result.getRow());
        //在已经知道列名的前提之下获取对应的列值
        String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
        String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
        String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
        String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
        System.out.println("学号:" + id + ",姓名:" + name + ",年龄:" + age + ",性别:" + gender + ",班级:" + clazz);
//        System.out.println("-----------------");
    }




    /**
     * 释放Before创建的资源,在每个Test之后执行
     */
    @After
    public void closeSource() {
        try {
            if (admin != null) {
                admin.close();
            }

            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

我们可以将上述的API实现方式封装为一个工具类HBaseUtil,方便我们后续使用:

import com.shujia.bean.MyCell;
import com.shujia.bean.NotFoundFilterNameException;
import com.shujia.bean.NotFountComparatorException;
import jdk.nashorn.internal.codegen.types.BooleanType;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

public class HBaseUtil {
    public static Connection CONNECTION;
    public static Admin ADMIN;

    private HBaseUtil() {
    }

    /**
     * 获取数据库连接对象和数据库操作对象
     */
    static {
        try {
            //1、获取hbase集群的配置文件对象
            //0.90.0之前旧版本的写法:
//        HBaseConfiguration conf = new HBaseConfiguration();
            //新版本的写法:调用静态方法public static Configuration create()
            Configuration conf = HBaseConfiguration.create();

            //2、因为hbase的数据都有一条元数据,而元数据也存储在一张表中,这张元数据表也有元数据,存储在zookeeper中
            //配置文件要设置你自己的zookeeper集群
//            conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181"); //前提时windows中配置了hosts映射
            Properties prop = new Properties();
            prop.load(new BufferedReader(new FileReader("E:\\projects\\IDEAProjects\\bigdata29\\hbase\\src\\main\\resources\\hbase.properties")));

            String zk = (String) prop.get("hbase.zookeeper.quorum");

            //2、因为hbase的数据都有一条元数据,而元数据也存储在一张表中,这张元数据表也有元数据,存储在zookeeper中
            //配置文件要设置你自己的zookeeper集群
            conf.set("hbase.zookeeper.quorum", zk); //前提时windows中配置了hosts映射

            //3、获取数据库的连接对象
            CONNECTION = ConnectionFactory.createConnection(conf);

            //4、获取数据库操作对象
//            HBaseAdmin hBaseAdmin = new HBaseAdmin(conn);
            //新版本的做法
            ADMIN = CONNECTION.getAdmin(); //使用连接对象获取数据库操作对象
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createOneTable(String tableName, String columnFamily) {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf(tableName);
            if (!ADMIN.tableExists(tn)) {
                TableDescriptorBuilder students = TableDescriptorBuilder.newBuilder(tn);
//                ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of(columnFamily);

                //使用另外一种方式创建列簇并设置布隆过滤器
                ColumnFamilyDescriptor columnFamilyDescriptor = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily))
                        .setBloomFilterType(BloomType.ROW).build();


                students.setColumnFamily(columnFamilyDescriptor);
                ADMIN.createTable(students.build());
                System.out.println(tn + "表创建成功!!!");
            } else {
                System.out.println(tn + "表已经存在!");
            }
        } catch (Exception e) {
            System.out.println("表创建失败!!");
            e.printStackTrace();
        }
    }

    /**
     * 需求:2、如何删除一张表
     * disable 'students'
     * drop 'students'
     */
    public static void dropOneTable(String tableName) {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf(tableName);
            //判断表是否存在
            if (ADMIN.tableExists(tn)) {
                //先禁用表
                ADMIN.disableTable(tn);
                ADMIN.deleteTable(tn);
                System.out.println(tn + "表成功被删除");
            } else {
                System.out.println(tn + "表不存在!!");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 需求:3、如何向一张表中添加一条数据
     * put 'students','1001','info:name','小虎'
     */
    public static void putOneDataToTable(String tableName, String rowKey, String columnFamily, String colName, String colValue) {
        try {
            //先将表名封装成一个TableName的对象
            TableName tn = TableName.valueOf(tableName);

            //判断表是否存在
            if (ADMIN.tableExists(tn)) {
                //获取表对象
                Table students = CONNECTION.getTable(tn);
                //hbase自带的一个工具类Bytes,可以将字符串转字节数组
                Put put = new Put(Bytes.toBytes(rowKey));//行键的字节数组形式
                put.add(new KeyValue(Bytes.toBytes(rowKey),
                        Bytes.toBytes(columnFamily),
                        Bytes.toBytes(colName),
                        Bytes.toBytes(colValue)));
                //void put(Put put)
                //需要先将我们添加的列数据封装成一个Put对象
                students.put(put);
            } else {
                System.out.println(tn + "表不存在!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 需求:5、如何获取一条数据
     * get 'students','1500101000'
     */
    public static List<MyCell> getOneData(String tableName, String rowKey) throws Exception {
        //将表名封装TableName对象
        TableName sd = TableName.valueOf(tableName);
        //获取表的对象
        Table students = CONNECTION.getTable(sd);

        //传入行键的字节数组的形式
        Get get = new Get(Bytes.toBytes(rowKey));
        Result result = students.get(get);

        //创建List集合List<MyCell>  MyCell:行键,列簇,列名,列值,
        ArrayList<MyCell> myCells = new ArrayList<>();
        byte[] rk = result.getRow();
        //当不清楚列名的时候该如何获取呢?
        //获取一行中的所有单元格组合的集合
        List<Cell> cells = result.listCells(); //获取的结果值的顺序是hbase中存储排序后的顺序
        //遍历集合得到每个单元格,获取每个列值
        for (Cell cell : cells) {
            byte[] family = CellUtil.cloneFamily(cell);
            byte[] qualifier = CellUtil.cloneQualifier(cell);
            byte[] value = CellUtil.cloneValue(cell);
            myCells.add(new MyCell(rk, family, qualifier, value));
        }
        return myCells;
    }


    /**
     * 7、如果获取一批数据 第二种方式
     * scan 'students' 默认情况下获取表所有数据
     * scan 'students',LIMIT=>3
     */
    public static void scanData(String tableName) {
        try {
            TableName sd = TableName.valueOf(tableName);
            Table students = CONNECTION.getTable(sd);
            //创建Scan对象
            Scan scan = new Scan(); //查询表中的所有行

            //default ResultScanner getScanner(Scan scan)
            ResultScanner resultScanner = students.getScanner(scan);
            //通过观察源码发现,可以先获取迭代器对象
            for (Result result : resultScanner) {
                printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void scanData(String tableName, String startRow, String endRow, boolean include) {
        try {
            TableName sd = TableName.valueOf(tableName);
            Table students = CONNECTION.getTable(sd);
            //创建Scan对象
            Scan scan = new Scan(); //查询表中的所有行
            //设置开始行和结束行
            if (include) {
                scan.withStartRow(Bytes.toBytes(startRow));
                scan.withStopRow(Bytes.toBytes(endRow), true);
            } else {
                scan.withStartRow(Bytes.toBytes(startRow));
                scan.withStopRow(Bytes.toBytes(endRow));
            }

            //default ResultScanner getScanner(Scan scan)
            ResultScanner resultScanner = students.getScanner(scan);
            //通过观察源码发现,可以先获取迭代器对象
            for (Result result : resultScanner) {
                printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void scanData(String tableName, int limit) {
        try {
            TableName sd = TableName.valueOf(tableName);
            Table students = CONNECTION.getTable(sd);
            //创建Scan对象
            Scan scan = new Scan(); //查询表中的所有行
            scan.setLimit(limit);

            //default ResultScanner getScanner(Scan scan)
            ResultScanner resultScanner = students.getScanner(scan);
            //通过观察源码发现,可以先获取迭代器对象
            for (Result result : resultScanner) {
                printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static ResultScanner scanDataReturn(String tableName, int limit) throws Exception{
        TableName sd = TableName.valueOf(tableName);
        Table students = CONNECTION.getTable(sd);
        //创建Scan对象
        Scan scan = new Scan(); //查询表中的所有行
        scan.setLimit(limit);

        //default ResultScanner getScanner(Scan scan)
        return students.getScanner(scan);
    }

    /**
     * 需求:7、如何创建预分region表
     * 将来对于某一个RegionServer而言,可能会接收大量的并发请求,超出了该RegionServer承受的压力,有可能会导致该子节点崩溃
     * 如果大量的并发请求查询的数据是多种多种多样的,只不过巧合的是都在一个RegionServer上管理
     * 解决的思路:分散查询的数据到不同的RegionServer上,这样请求也会随着被分散到不同的RegionServer上,就达到了减轻某一个RegionServer压力过大情况,解决了单点故障的问题
     */
    public static void createPreviewTable(String tableName, String columnFamily, byte[][] splitKeys) {
        try {
            //先将表名封装成TableName对象
            TableName tb = TableName.valueOf(tableName);

            //创建表描述器对象
            TableDescriptorBuilder tbSplit2 = TableDescriptorBuilder.newBuilder(tb);

            //创建列簇描述器对象
            ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of(columnFamily);

            //将列簇添加到表中
            tbSplit2.setColumnFamily(info);


            //调用方法创建表
//            admin.createTable(tbSplit2.build());
            //调用另外一个方法,传入表描述器的同时,传入分割点,创建预分region表
            //void createTable(TableDescriptor desc, byte[][] splitKeys)
            ADMIN.createTable(tbSplit2.build(), splitKeys);
            System.out.println(tableName + "预分region表创建成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 编写一个方法专门做比较过滤器的
     * <p>
     * 需要考虑的参数:表名 过滤器 操作符 比较器 值
     */
    public static void scanDataWithCompareFilter(String tableName, String filterType, CompareOperator compareOperator,
                                                 String comparatorType, String value) {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf(tableName);
            Table students = CONNECTION.getTable(st);
            Scan scan = new Scan();
            ByteArrayComparable byteArrayComparable = null;

            switch (comparatorType) {
                case "BinaryComparator":
                    byteArrayComparable = new BinaryComparator(Bytes.toBytes(value));
                    break;
                case "BinaryPrefixComparator":
                    byteArrayComparable = new BinaryPrefixComparator(Bytes.toBytes(value));
                    break;
                case "SubstringComparator":
                    byteArrayComparable = new SubstringComparator(value);
                    break;
                default:
                    throw new NotFountComparatorException("没有匹配的比较器!使用ComparableName获取");
            }


            //--------------------------------------------------------------------------------
            CompareFilter compareFilter = null;
            switch (filterType) {
                case "RowFilter":
                    compareFilter = new RowFilter(compareOperator, byteArrayComparable);
                    break;
                case "FamilyFilter":
                    compareFilter = new FamilyFilter(compareOperator, byteArrayComparable);
                    break;
                case "QualifierFilter":
                    compareFilter = new QualifierFilter(compareOperator, byteArrayComparable);
                    break;
                case "ValueFilter":
                    compareFilter = new ValueFilter(compareOperator, byteArrayComparable);
                    break;
                default:
                    throw new NotFoundFilterNameException("没有匹配的比较过滤器!使用FilterName获取");
            }

            //--------------------------------------------------------------------------------

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(compareFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void printResult(Result result) {
        List<Cell> cells = result.listCells();
        StringBuffer sb = new StringBuffer();

        String rk = Bytes.toString(result.getRow());
        sb.append(rk).append(",");
        for (int i = 0; i < cells.size(); i++) {
            String fa = Bytes.toString(CellUtil.cloneFamily(cells.get(i)));
            String qName = Bytes.toString(CellUtil.cloneQualifier(cells.get(i)));
            String colName = Bytes.toString(CellUtil.cloneValue(cells.get(i)));
            if (i == cells.size() - 1) {
                sb.append(fa).append(":").append(qName).append("-").append(colName); // 1001,info:name-xiaohu,info:age-18
            } else {
                sb.append(fa).append(":").append(qName).append("-").append(colName).append(",");
            }
        }
        System.out.println(sb);
    }


    /**
     * 释放Before创建的资源,在每个Test之后执行
     */
    public static void closeSource() {
        try {
            if (ADMIN != null) {
                ADMIN.close();
            }

            if (CONNECTION != null) {
                CONNECTION.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

 

二、过滤器

比较过滤器:

1、行键过滤器:RowFilter
2、列簇过滤器:FamilyFilter
3、列名过滤器:QualifierFilter
4、列值过滤器:ValueFilter 

专用过滤器:

5、单列值过滤器:SingleColumnValueFilter

SingleColumnValueFilter会返回满足条件的cell所在行的所有cell的值(即会返回一行数据)

6、列值排除过滤器:SingleColumnValueExcludeFilter

与SingleColumnValueFilter相反,会排除掉指定的列,其他的列全部返回

7、rowkey前缀过滤器:PrefixFilter
8、分页过滤器PageFilter
9、包装过滤器:

(1)SkipFilter过滤器:SkipFilter包装一个过滤器,当被包装的过滤器遇到一个需要过滤的 KeyValue 实例时,则拓展过滤整行数据。

(2)WhileMatchFilter过滤器:WhileMatchFilter 包装一个过滤器,当被包装的过滤器遇到一个需要过滤的 KeyValue 实例时,WhileMatchFilter 则结束本次扫描,返回已经扫描到的结果。

10、多过滤器综合查询:

以上都是讲解单个过滤器的作用,当需要多个过滤器共同作用于一次查询的时候,就需要使用 FilterListFilterList 支持通过构造器或者 addFilter 方法传入多个过滤器。

代码实现: 

import com.shujia.bean.ComparableName;
import com.shujia.bean.FilterName;
import com.shujia.utils.HBaseUtil;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;

public class HBaseFilter {
    private Connection conn;
    private Admin admin;

    /**
     * 在所有Test方法执行之前执行
     */
    @Before
    public void getConnection() {
        conn = HBaseUtil.CONNECTION;
        admin = HBaseUtil.ADMIN;
    }


    /**
     *行键过滤器RowFilter:
     *需求:通过RowFilter与BinaryComparator(二进制内容比较器)过滤比rowKey 1500100010小的所有值出来
     * 配合等值比较器BinaryComparator
     */
    @Test
    public void scanDataWithRowFilterAndBinaryComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建一个BinaryComparator比较器对象
            BinaryComparator binaryComparator = new BinaryComparator(Bytes.toBytes("1500100010"));

            //创建一个行键过滤器对象
            //旧版本创建方式:public RowFilter(final CompareOp rowCompareOp,final ByteArrayComparable rowComparator)
//            RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.LESS, binaryComparator);
            //新版本创建方式:public RowFilter(final CompareOperator op,final ByteArrayComparable rowComparator)
            RowFilter rowFilter = new RowFilter(CompareOperator.LESS, binaryComparator);

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(rowFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 列簇过滤器:FamilyFilter
     * 需求:过滤出列簇名中包含“a”的列簇中所有数据配合包含比较器SubstringComparator
     */
    @Test
    public void scanDataWithFamilyFilterAndSubstringComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("users");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建一个包含比较器
            SubstringComparator substringComparator = new SubstringComparator("f");

            //创建列簇过滤器
            //public FamilyFilter(final CompareOperator op, final ByteArrayComparable familyComparator)
            FamilyFilter familyFilter = new FamilyFilter(CompareOperator.EQUAL, substringComparator);


            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(familyFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 列名过滤器:QualifierFilter
     * 通过QualifierFilter与SubstringComparator(包含比较器)查询列名包含 m 的列的值
     */
    @Test
    public void scanDataWithQualifierFilterAndSubstringComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("users");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建一个包含比较器
            SubstringComparator substringComparator = new SubstringComparator("m");

            //创建列名过滤器
            //public QualifierFilter(final CompareOperator op, final ByteArrayComparable qualifierComparator)
            QualifierFilter qualifierFilter = new QualifierFilter(CompareOperator.EQUAL, substringComparator);

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(qualifierFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 列值过滤器(属于比较过滤器)
     * 通过ValueFilter与BinaryPrefixComparator(二进制前缀比较器)过滤出所有的cell中值以 "从" 开头的学生
     * 注意:列值过滤器只能过滤出当前符合条件的列,至于与该列属于同一行的其他列并不会返回
     */
    @Test
    public void scanDataWithValueFilterAndBinaryPrefixComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建二进制前缀比较器
            BinaryPrefixComparator binaryPrefixComparator = new BinaryPrefixComparator(Bytes.toBytes("从"));

            //创建列值过滤器对象
            //public ValueFilter(final CompareOperator valueCompareOp, final ByteArrayComparable valueComparator)
            ValueFilter valueFilter = new ValueFilter(CompareOperator.EQUAL, binaryPrefixComparator);

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(valueFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 单列值过滤器(专用过滤器)
     * 需求:通过SingleColumnValueFilter与BinaryPrefixComparator过滤出所有的cell中值以 "从" 开头的学生
     */
    @Test
    public void scanDataWithSingleColumnValueFilterAndBinaryPrefixComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建二进制前缀比较器
            BinaryPrefixComparator binaryPrefixComparator = new BinaryPrefixComparator(Bytes.toBytes("从"));

            //创建单列值过滤器
            //public SingleColumnValueFilter(final byte [] family, final byte [] qualifier,
            //      final CompareOperator op,
            //      final org.apache.hadoop.hbase.filter.ByteArrayComparable comparator)
            SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("name"),
                    CompareOperator.EQUAL, binaryPrefixComparator);

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(singleColumnValueFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 列值排除过滤器
     * SingleColumnValueExcludeFilter
     * 通过SingleColumnValueExcludeFilter与BinaryComparator查询文科一班所有学生信息,最终不返回clazz列
     */
    @Test
    public void scanDataWithSingleColumnValueExcludeFilterAndBinaryComparator() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建二进制内容比较器
            BinaryComparator binaryComparator = new BinaryComparator(Bytes.toBytes("文科一班"));

            //创建列值排除过滤器
            //public SingleColumnValueExcludeFilter(byte[] family, byte[] qualifier,
            //                                        CompareOperator op, ByteArrayComparable comparator)
            SingleColumnValueExcludeFilter singleColumnValueExcludeFilter = new SingleColumnValueExcludeFilter(Bytes.toBytes("info"), Bytes.toBytes("clazz"),
                    CompareOperator.EQUAL, binaryComparator);

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(singleColumnValueExcludeFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 行键前缀过滤器  PrefixFilter
     * 通过PrefixFilter查询以15001001开头的所有前缀的rowkey
     */
    @Test
    public void scanDataWithPrefixFilter() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //PrefixFilter(final byte [] prefix)
            PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("150010093"));

            //设置过滤器
            //public Scan setFilter(Filter filter)
            scan.setFilter(prefixFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 分页过滤器
     * PageFilter
     * 通过PageFilter查询三页的数据,每页10条
     */
    @Test
    public void scanDataWithPageFilter() {
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);

            //设置几个变量
            //设置要查询的页数
            int pageNum = 5;
            //设置每一页要查询的条数
            int pageNumData = 10;
            //设置开始行
            String startRowKey = "";

            //创建分页过滤器对象
            PageFilter pageFilter = new PageFilter(pageNumData);
            //创建Scan的对象
            Scan scan = new Scan();
            scan.setFilter(pageFilter);

            for (int i = 1; i <= pageNum; i++) {
                System.out.println("====================当前是第 " + i + " 页=========================");
                //查询10条数据
                ResultScanner resultScanner = students.getScanner(scan);
                //获取该页的最后一行的行键
                for (Result result : resultScanner) {
                    startRowKey = Bytes.toString(result.getRow()) + 0;
                    //设置下一行的开始
                    scan.withStartRow(Bytes.toBytes(startRowKey));
                    HBaseUtil.printResult(result);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 包装过滤器之SkipFilter过滤器
     *
     * 1500100071,祖昌勋,22,男,理科四班
     */
    @Test
    public void scanDataWithSkipFilter(){
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            ValueFilter valueFilter = new ValueFilter(CompareOperator.NOT_EQUAL, new SubstringComparator("理科"));

            //创建跳过过滤器
            //SkipFilter(Filter filter)
            SkipFilter skipFilter = new SkipFilter(valueFilter);

            scan.setFilter(skipFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 包装过滤器之WhileMatchFilter过滤器
     *
     * 1500100071,祖昌勋,22,男,理科四班
     */
    @Test
    public void scanDataWithWhileMatchFilter(){
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            ValueFilter valueFilter = new ValueFilter(CompareOperator.NOT_EQUAL, new SubstringComparator("祖昌勋"));

            //创建跳过过滤器
            //SkipFilter(Filter filter)
            WhileMatchFilter whileMatchFilter = new WhileMatchFilter(valueFilter);

            scan.setFilter(whileMatchFilter);

            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 组合过滤器
     * 需求:通过运用4种比较器过滤出姓于,年纪大于22岁,性别为女,且是理科的学生。
     */
    @Test
    public void scanDataWithGroupFilter(){
        try {
            /**
             * CompareFilter 是一个抽象类,无法被实例化
             * 但是,我们通过观察源码,可以得到一些信息,创建比较过滤器对象的时候,至少需要传入两种参数:操作符,比较器
             */
            //获取表对象
            TableName st = TableName.valueOf("students");
            Table students = conn.getTable(st);
            Scan scan = new Scan();

            //创建单列值过滤器
            //过滤出姓于的
            SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("name"),
                    CompareOperator.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("于")));

            //年纪大于22岁
            SingleColumnValueFilter singleColumnValueFilter1 = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("age"),
                    CompareOperator.GREATER, new BinaryComparator(Bytes.toBytes("22")));

            //性别为女
            SingleColumnValueFilter singleColumnValueFilter2 = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("gender"),
                    CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("女")));

            //理科
            SingleColumnValueFilter singleColumnValueFilter3 = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("clazz"),
                    CompareOperator.EQUAL, new SubstringComparator("理科"));

            //如何以每次添加一个过滤器作为条件的话,后一次添加的过滤器逻辑会将前一次覆盖
//            scan.setFilter(singleColumnValueFilter);
//            scan.setFilter(singleColumnValueFilter1);
//            scan.setFilter(singleColumnValueFilter2);
//            scan.setFilter(singleColumnValueFilter3);

            //通过观察源码发现,虽然setFilter这个方法只能传Filter的子类对象
            //但是我们发现了该抽象类的一个子类FilterList表示多个过滤器集合的意思
            //所以我们可以先创建FilterList对象,将多个过滤器封装成List集合添加到FilterList对象中,最终将FilterList对象再添加到scan中
            //先将上面4个过滤器添加到List集合中
            ArrayList<Filter> filters = new ArrayList<>();
            filters.add(singleColumnValueFilter);
            filters.add(singleColumnValueFilter1);
            filters.add(singleColumnValueFilter2);
            filters.add(singleColumnValueFilter3);

            //创建FilterList对象
            FilterList filterList = new FilterList();
            //public void addFilter(List<Filter> filters)
            filterList.addFilter(filters);


            scan.setFilter(filterList);


            ResultScanner resultScanner = students.getScanner(scan);
            for (Result result : resultScanner) {
                HBaseUtil.printResult(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testHBaseUtil() {
        //需求:通过RowFilter与BinaryComparator过滤比rowKey 1500100010小的所有值出来
//        HBaseUtil.scanDataWithCompareFilter("students", FilterName.ROWKEY,
//                CompareOperator.LESS,ComparableName.BINARY,"1500100010");

        //需求:过滤出列簇名中包含“a”的列簇中所有数据配合包含比较器SubstringComparator
//        HBaseUtil.scanDataWithCompareFilter("users",FilterName.FAMILY,
//                CompareOperator.EQUAL,ComparableName.SUBSTRING,"a");

        //需求:通过QualifierFilter与SubstringComparator查询列名包含 m 的列的值
//        HBaseUtil.scanDataWithCompareFilter("users",FilterName.QUALIFIER,
//                CompareOperator.EQUAL,ComparableName.SUBSTRING,"m");

        //需求:通过ValueFilter与BinaryPrefixComparator过滤出所有的cell中值以 "从" 开头的学生
        HBaseUtil.scanDataWithCompareFilter("students", FilterName.VALUE,
                CompareOperator.EQUAL, ComparableName.BINARY_PREFIX, "从");

    }


    /**
     * 释放Before创建的资源,在每个Test之后执行
     */
    @After
    public void closeSource() {
        HBaseUtil.closeSource();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/571102.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

脚手架搭建项目package.json配置中依赖的版本问题

脚手架搭建项目package.json配置中依赖的版本问题 问题描述&#xff1a;项目刚搭建好&#xff0c;运行没有问题&#xff0c;为什么过一段时间&#xff0c;删除node_modules&#xff0c;或者重新安装包依赖&#xff0c;然后项目某些地方出现莫名的错误&#xff08;依赖库的地方…

希捷HDD最新财报:销售同比下降11%,环比增长6%,4Q24前景看好

Seagate Technology Holdings plc公布了截至2024年3月29日的第三财季财务业绩。 “随着云需求改善、我们强大的运营纪律和价格执行&#xff0c;希捷3月季度的营收增长了6%&#xff0c;非GAAP每股收益较上一季度翻了一番多。这种组合为我们市场复苏时回归目标利润率奠定了基础。…

C++:类与对象完结篇

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;运算符重载》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 重新认识构造函数1.初始化列表2.explicit关键字 static成员1.sta…

面试:ThreadLocal

目录 1、ThreadLocal可以实现〔资源对象】的线程隔离&#xff0c;让每个线程各用各的【资源对象】&#xff0c;避免争用引发的线程安全问题 2、ThreadLocal同时实现了线程内的资源共享 3、原理 4、为什么ThreadLocalMap 中的 key (即 ThreadLocal &#xff09;要设计为弱引用…

configure: error: library ‘crypto‘ is required for OpenSSL

1、执行命令./configure --prefix/usr/local/pgsql/postgresql-14.2 --with-openssl 报错configure: error: library crypto is required for OpenSSL 2、解决办法 yum install openssl openssl-devel

pom文件依赖报红问题

dependencyManagement标签下依赖报红 如图 dependencyManagement标签下依赖报红问题&#xff0c;原因是dependencyManagement标签下的包不会被下载&#xff0c;repository里根本没有 解决方法 &#xff1a;将依赖复制到dependencies标签下&#xff0c;再reload pom文件&#x…

Leetcode算法训练日记 | day35

专题九 贪心算法 一、柠檬水找零 1.题目 Leetcode&#xff1a;第 860 题 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然…

为什么建议游戏工作室使用海外住宅IP防封?

当谈到游戏工作室时&#xff0c;它们通常以多开游戏账号来获取收益为主要目标。这种商业模式在游戏产业中已经成为一个独特而且颇具潜力的领域。然而&#xff0c;随之而来的是防封问题&#xff0c;特别是当游戏工作室试图通过多开账号来赚取更多收益时。因此&#xff0c;我们有…

【第6节】Lagent AgentLego 智能体应用搭建

目录 1 基础课程2 安装环境2.1 教程要求2.2 安装 Lagent 和 AgentLego 3 实践操作3.1 Lagent&#xff1a;轻量级智能体框架3.1.1 Lagent Web Demo 使用3.1.2 用 Lagent 自定义工具 3.2 AgentLego&#xff1a;组装智能体“乐高”3.2.1 AgentLego 直接使用部分3.2.2 AgentLego We…

【Harmony3.1/4.0】笔记二

概述 列表是一种复杂的容器&#xff0c;当列表项达到一定数量&#xff0c;内容超过屏幕大小时&#xff0c;可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集&#xff0c;例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求&#xff08;如通讯录、…

linux——yum工具详解

yum是linux中自动解决软件包依赖关系的管理器 同时&#xff0c;yum也是一个rpm软件 这里使用yum install nginx安装nginx

Windows SMBGhost CVE-2020-0796 Elevate Privileges

SMBGhost CVE-2020-0796 Microsoft Windows 10 (1903/1909) - ‘SMBGhost’ SMB3.1.1 ‘SMB2_COMPRESSION_CAPABILITIES’ Local Privilege Escalation https://www.exploit-db.com/exploits/48267 Github https://github.com/danigargu/CVE-2020-0796 修改载荷[可选] 生成 c# …

用c++实现起泡排序、哈密顿回路问题、TSP问题

5.3.2 起泡排序 【问题】 起泡排序(bubble sort)的基本思想是&#xff1a;两两比较相邻记录&#xff0c;如果反序则交换&#xff0c;直至没有反序的记录&#xff0c;如图5.8所示。【想法】下表给出了一个起泡排序的例子&#xff08;方括号括起来的为无序区&#xff09;&#x…

深入理解JavaScript:对象什么时候创建

&#x1f31f; 我们在chrome浏览器中debug程序。为了好debug我们会写一些在日常开发中基本不会采用的代码书写方式。 JavaScript中创建对象有3中方式&#xff1a; 1、对象字面量&#xff1b; 2、new&#xff1b; 3、Object.create(对象)&#xff1b; 1、使用new创建对象 fun…

MicroSIP电话呼叫软件使用及配置方法

MicroSIP是一款开源的SIP协议电话软件&#xff0c;它可以帮助你在计算机上进行语音和视频通话。下面是关于如何使用和配置MicroSIP的一些基本步骤&#xff1a; 安装MicroSIP 从MicroSIP官方网站下载适合你操作系统的安装包23。 解压下载的文件&#xff0c;并运行安装程序。 …

GRPC学习笔记

GRPC学习笔记 1 GRPC简介 1.1 定义 gRPC&#xff08;Google Remote Procedure Call&#xff0c;Google远程过程调用&#xff09;协议是谷歌发布的基于HTTP2协议承载的高性能、通用的RPC开源软件框架&#xff0c;提供了支持多种编程语言的、对网络设备进行配置和管理的方法。…

更新至2022年上市公司数字化转型数据合集(四份数据合集)

更新至2022年上市公司数字化转型数据合集&#xff08;四份数据合集&#xff09; 一、2000-2022年上市公司数字化转型数据&#xff08;年报词频、文本统计&#xff09; 二、2007-2022年上市公司数字化转型数据&#xff08;年报和管理层讨论&#xff09;&#xff08;含原始数据…

Java中的运算符

运算符是用于数学函数、一些特殊的赋值语句和逻辑比较方面的特殊符号。 赋值运算符&#xff08;“”&#xff09; 赋值运算符是一个二元运算符&#xff08;即对两个操作数进行处理&#xff09;&#xff0c;功能是将右侧的操作数赋值给左侧的操作数。 int a 100; 该表达式就…

prometheus配置监控Java应用服务

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

从底层分析并详解SpringAOP底层实现

首先分析AOP的实现 首先切面&#xff08;Advisor&#xff09;由通知(Advice)和切点(Pointcut)组成 包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知 先看一段代码了解一下是aop是怎么运作的 首先定义了两个类实现了MethodInterceptor接口&…
最新文章