要想通过ES API对es的操作,必须获取到TransportClient对象,让后根据TransportClient获取到IndicesAdminClient对象后,方可以根据IndicesAdminClient对象提供的方法对ES的index进行操作:create index,update index(update index settings,update index mapping),delete index,open index,close index。

准备工作(创建TransportClient,IndicesAdminClient)

第一步:导入ES6.4.2的依赖包:

    <dependencies>
<!--Spark -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql-kafka-0-10_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.twitter</groupId>
<artifactId>bijection-avro_2.11</artifactId>
<version>0.9.5</version>
</dependency>
<dependency>
<groupId>com.databricks</groupId>
<artifactId>spark-avro_2.11</artifactId>
<version>3.2.0</version>
<type>jar</type>
</dependency> <dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-spark-20_2.11</artifactId>
<version>6.4.2</version>
</dependency> <dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.4.2</version>
</dependency>
</dependencies>

备注:这里依赖可能有点多,elastricsearch api操作的话就是依赖org.elasticsearch.client。

第二步:获取TransportClient,IndicesAdminClient对象:

    /**
* 获取ES Client API对象。
* */
public static TransportClient getClient() {
Map<String, String> esOptionsMap = getSparkESCommonOptions(); return getClient(esOptionsMap);
} /**
* 获取ES Client API对象。
* */
public static TransportClient getClient(Map<String, String> esOptionsMap) {
Settings settings = Settings.builder()//
.put("cluster.name", esOptionsMap.get("cluster.name")) //
.put("client.transport.sniff", true)//
.build(); PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
TransportClient client = preBuiltTransportClient; // 192.168.1.120,192.168.1.121,192.168.1.122,192.168.1.123
String esNodeStr = esOptionsMap.get("es.nodes");
String[] esNodeArr = esNodeStr.split(","); try {
for (String esNode : esNodeArr) {
client.addTransportAddress(new TransportAddress(InetAddress.getByName(esNode), 9300));
}
} catch (UnknownHostException e) {
e.printStackTrace();
throw new RuntimeException(e);
} return client;
} public static IndicesAdminClient getAdminClient() {
Map<String, String> esOptionsMap = getSparkESCommonOptions(); return getAdminClient(esOptionsMap);
} public static IndicesAdminClient getAdminClient(Map<String, String> esOptionsMap) {
TransportClient client = getClient(esOptionsMap);
IndicesAdminClient adminClient = client.admin().indices();
return adminClient;
}

备注:其中getSparkESCommonOptions()中配置对象包含:

cluster.name=es-application
es.nodes=192.168.1.120,192.168.1.121,192.168.1.122,192.168.1.123
es.port=9200
es.index.auto.create=true
pushdown=true
es.nodes.wan.only=true
es.mapping.date.rich=false #//设置读取es中date数据类型字段时,把它当做string来读取。
es.scroll.size=10000

ES API之Exists/Create Index:

创建index之前,需要判断index及其对应的类型是否存在,使用这个方法:

    /**
* 是否ES包含某个索引类型
*
* @param indexName
* index
* @param indexType
* index对应的type
* */
public static boolean typeExists(String indexName, String indexType) {
TypesExistsResponse typeResponse = getAdminClient().prepareTypesExists(indexName).setTypes(indexType).execute().actionGet();
if (typeResponse.isExists()) {
return true;
}
return false;
} /**
* 判断ES中是否存在某个index<br>
* 是否包含类型,待验证,看别人调用时是不需要带类型的。
* */
public static boolean indexExists(String... indices) {
IndicesExistsRequest request = new IndicesExistsRequest(indices);
IndicesExistsResponse response = getAdminClient().exists(request).actionGet();
if (response.isExists()) {
return true;
}
return false;
}

创建index,包含两种:不指定mapping和isettings只创建一个空的index;指定mapping和settings创建复杂的index。

创建一个空的index:

    /**
* 创建简单索引——没有指定mapping<br>
* 此时数据插入时,会读取数据的数据的字段名称,自动创建mapping字段(但是,存在问题数据类型不能完好的控制,比如double类型可能会被匹配为float,date类型的格式消失)
* */
public static boolean indexCreate(String indexName) {
CreateIndexResponse response = getAdminClient().prepareCreate(indexName).get();
return response.isAcknowledged();
}

备注:此时数据插入时,会读取数据的数据的字段名称,自动创建mapping字段(但是,存在问题数据类型不能完好的控制,比如double类型可能会被匹配为float,date类型的格式消失)

创建复杂的index:

    /**
* 创建复杂索引(类型/mapping),指定索引的setting和mapping,其中mappingSource是一个json数据字符串。
*
* @param indexName
* 索引名
* @param indexType
* 索引类型名
* @param builder
* 索引mapping
*/
public static boolean indexCreate(String indexName, String indexType, XContentBuilder builder) {
Settings settings = Settings.builder() //
.put("index.mapping.ignore_malformed", true)//
.put("index.refresh_interval", "60s") //
.put("index.number_of_shards", 4)//
.put("index.number_of_replicas", 0)//
.put("index.max_result_window", 500000)// .put("index.translog.durability", "async")//
.put("index.translog.sync_interval", "120s")//
.put("index.translog.flush_threshold_size", "2gb")// .put("index.merge.scheduler.max_thread_count", 1)//
.build(); return indexCreate(indexName, indexType, builder, settings);
} /**
* 创建复杂索引(类型/mapping),指定索引的setting和mapping,其中mappingSource是一个json数据字符串。
*
* @param indexName
* 索引名
* @param indexType
* 索引类型名
* @param builder
* 索引mapping
* @param settings
* 索引settings<br>
* setting http://192.168.1.120:9200/twitter/_settings?pretty<br>
* "settings":<br>
* {<br>
* ----"index":<br>
* ----{<br>
* --------"mapping":<br>
* --------{<br>
* ------------"ignore_malformed":"true"<br>
* --------},<br>
* --------"refresh_interval":"60s",<br>
* --------"number_of_shards":"4",<br>
* --------"translog":<br>
* --------{<br>
* ------------"flush_threshold_size":"2048m",<br>
* ------------"sync_interval":"120s",<br>
* ------------"durability":"async"<br>
* --------},<br>
* --------"provided_name":"indexName",<br>
* --------"merge":{<br>
* ------------"scheduler":<br>
* ------------{<br>
* ----------------"max_thread_count":"1"<br>
* ------------}<br>
* --------},<br>
* --------"max_result_window":"500000",<br>
* --------"creation_date":"1540781909323",<br>
* --------"number_of_replicas":"0",<br>
* --------"uuid":"5c079b5tQrGdX0fF23xtQA",<br>
* --------"version":{"created":"6020499"}<br>
* ----}<br>
* }<br>
*/
public static boolean indexCreate(String indexName, String indexType, XContentBuilder builder, Settings settings) {
if (indexExists(indexName)) {
return false;
} // CreateIndexResponse准备创建索引,增加setSetting()方法可以设置setting参数,否则将会按默认设置
CreateIndexResponse cIndexResponse = getAdminClient().prepareCreate(indexName)//
.setSettings(settings)// setting
.addMapping(indexType, builder)// type,mapping 这种方式也可以,经过测试。
.get(); return cIndexResponse.isAcknowledged();
}

如何根据Avro创建动态生成Mapping呢?

    /**
* 重建index
*
* @throws IOException
* */
protected void createIndex(String indexName, String indexType) throws IOException {
Tuple3<List<String>, Map<String, String>, ExpressionEncoder<Row>> src = getTargetSchema(srcSchemaKey, true); Map<String, Map<String, String>> extFields = new HashMap<String, Map<String, String>>();
Map<String, String> insertDateProperty = new HashMap<String, String>();
insertDateProperty.put("type", "date");
insertDateProperty.put("format", "yyyy-MM-dd");
extFields.put("index_date", insertDateProperty);
Map<String, String> typeProperty = new HashMap<String, String>();
typeProperty.put("type", "keyword");
extFields.put("type", typeProperty); XContentBuilder mappingSource = getMapping(indexType, src._2(), extFields); if (!indexCreate(indexName, indexType, mappingSource)) {
throw new RuntimeException("重新创建index" + indexName + "时,设置mapping失败!");
}
}
/**
*
* @param indexType
* index类型
* @param schemaColVsTypeMap
* 从*.avsc schema文件中读取出的字段,格式:colName vs colType
* @param extFields
* 新增扩展字段(在*.avsc schema文件中没有包含的字段)<br>
* @return mapping:<br>
* {<br>
* ----"mrs_rsrp_d_2018.10.26":<br>
* ----{<br>
* --------"aliases":{},<br>
* --------"mappings":<br>
* --------{<br>
* -----------"_doc":{<br>
* -----------"properties":<br>
* -----------{<br>
* --------------"cgi":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},<br>
* --------------"timestamp":{"type":"long"}<br>
* -----------}<br>
* --------},<br>
* --------"settings":{}<br>
* ----}<br>
* }<br>
* @throws 生成XContentBuilder时
* ,抛出异常。
*/
public static XContentBuilder getMapping(String indexType, Map<String, String> schemaColVsTypeMap, Map<String, Map<String, String>> extFields)
throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder()//
.startObject()//
.startObject(indexType)//
.startObject("_all").field("enabled", false).endObject()// 是否包一个row中的所有字段作为一个大的索引字段,支持从所有列中查询
// .startObject("_source").field("enabled", false).endObject()// 不可以设为false,否则从es中查不到字段(其属性决定了那些字段存储到es,默认所有字段都存储,也可以通过include,exclude指定特定字段存储与不存储)
// .startObject("_field_names").field("enabled", false).endObject()//
.startObject("properties"); for (Map.Entry<String, String> kv : schemaColVsTypeMap.entrySet()) {
String colName = kv.getKey();
String colType = kv.getValue(); // "insert_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},
// "scan_start_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},
// "scan_stop_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},
if (colName.equalsIgnoreCase("scan_start_time")//
|| colName.equalsIgnoreCase("scan_stop_time")//
|| colName.equalsIgnoreCase("insert_time")) {
builder.startObject(colName) //
.field("type", "date")//
.field("format", "yyyy-MM-dd HH:mm:ss")// 也可以 yyyy/MM/dd||yyyy/MM/dd HH:mm:ss
.field("index", "true") // not_analyzed|analyzed
.endObject();
}
// "city_name":{"type":"text","fields":{"keyword":{"type":"keyword"}}},
// "province_name":{"type":"text","fields":{"keyword":{"type":"keyword"}}},
// "region_name":{"type":"text","fields":{"keyword":{"type":"keyword"}}},
else if (colName.equalsIgnoreCase("city_name")//
|| colName.equalsIgnoreCase("region_name")//
|| colName.equalsIgnoreCase("province_name")) {
builder.startObject(colName).field("type", "keyword").endObject();
} else {
if (colType.equalsIgnoreCase("long")) {
builder.startObject(colName).field("type", "long").endObject();
} else if (colType.equalsIgnoreCase("string")) {
builder.startObject(colName).field("type", "keyword").endObject();
} else if (colType.equalsIgnoreCase("double")) {
builder.startObject(colName).field("type", "double").endObject();
} else {
builder.startObject(colName).field("type", colType).endObject();
}
}
} // 追加扩展字段到mapping字段中
for (Map.Entry<String, Map<String, String>> kv : extFields.entrySet()) {
String colName = kv.getKey();
builder.startObject(colName); for (Map.Entry<String, String> kvProperty : kv.getValue().entrySet()) {
builder.field(kvProperty.getKey(), kvProperty.getValue());
}
builder.endObject();
} builder.endObject();// end of properties
builder.endObject();// end of indexType
builder.endObject();// end of start return builder;
} /**
* 返回 target columns list,column vs column type map,expression encoder
* */
protected Tuple3<List<String>, Map<String, String>, ExpressionEncoder<Row>> getTargetSchema(String schemaFilePath, boolean withTimestamp) {
Broadcast<String> targetSchemaContent = null;
try {
String avroContent = getHdfsFileContent(schemaFilePath);
targetSchemaContent = JavaSparkContext.fromSparkContext(sparkSession.sparkContext()).broadcast(avroContent);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} Schema.Parser parser = new Schema.Parser();
Schema targetSchema = parser.parse(targetSchemaContent.getValue());
List<String> targetColumns = new ArrayList<String>();
Map<String, String> targetKeyTypeItems = new LinkedHashMap<String, String>();
for (Field field : targetSchema.getFields()) {
targetColumns.add(field.name());
List<Schema> types = targetSchema.getField(field.name()).schema().getTypes();
String datatype = types.get(types.size() - 1).getName();
targetKeyTypeItems.put(field.name(), datatype);
} ExpressionEncoder<Row> encoder = SchemaHelper.createSchemaEncoder(targetSchema, withTimestamp); return new Tuple3<List<String>, Map<String, String>, ExpressionEncoder<Row>>(targetColumns, targetKeyTypeItems, encoder);
} /**
* 将schema转化为Encoder
*/
protected static ExpressionEncoder<Row> createSchemaEncoder(Schema schema, boolean withTimestamp) {
StructType type = (StructType) SchemaConverters.toSqlType(schema).dataType(); if (withTimestamp) {
List<String> fields = java.util.Arrays.asList(type.fieldNames());
if (!fields.contains("timestamp")) {
type = type.add("timestamp", DataTypes.TimestampType);
} else {
int index = type.fieldIndex("timestamp");
StructField field = type.fields()[index];
type.fields()[index] = new StructField(field.name(), DataTypes.TimestampType, field.nullable(), field.metadata());
}
} ExpressionEncoder<Row> encoder = RowEncoder.apply(type); return encoder;
} /**
* 读取hdfs上文件内容
*/
protected static String getHdfsFileContent(String filePath){
String content = "";
try {
reader = getHDFSFileReader(filePath);
String line=null;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("#") && line.trim().length() > 0) {
content+=line.trim();
}
} reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("file not found exception:" + this.avroSchemaPath);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("reading file while an error was thrown:" + this.avroSchemaPath);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} return content;
} protected static BufferedReader getHDFSFileReader(String hdfsFile) {
try {
System.out.println("hdfsfile: " + hdfsFile);
Path configPath = new Path(hdfsFile); FileSystem fs = FileSystem.get(new Configuration()); if (fs.exists(configPath)) {
return new BufferedReader(new InputStreamReader(fs.open(configPath)));
} else {
throw new FileNotFoundException("file(" + configPath + ") not found.");
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
}
}

所有代码都在这里,具体的不加介绍了。

ES API之Update Index:

所谓的修改index,也就是修改index的settings和mapping:

    /**
* 修改ES索引的mapping属性
* */
public static boolean indexUpdateMapping(String indexName, String indexType, XContentBuilder builder) {
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest mapping = Requests.putMappingRequest(indexName).type(indexType)
.source(builder);
PutMappingResponse pMappingResource = getAdminClient().putMapping(mapping).actionGet(); return pMappingResource.isAcknowledged();
} /**
* 修改ES索引的settings属性<br>
* 更新索引属性(更新索引的settings属性,这是更改已经创建的属性、但有些一旦创建不能更改,需要按照自己的需求来进行选择使用)
* */
public static boolean indexUpdatSettings(String indexName, Map<String, String> settingsMap) {
Builder settings = Settings.builder();//
for (Map.Entry<String, String> kv : settingsMap.entrySet()) {
settings.put(kv.getKey(), kv.getValue());
} return indexUpdatSettings(indexName, settings);
} /**
* 修改ES索引的settings属性<br>
* 更新索引属性(更新索引的settings属性,这是更改已经创建的属性、但有些一旦创建不能更改,需要按照自己的需求来进行选择使用)
* */
public static boolean indexUpdatSettings(String indexName, Builder settings) {
UpdateSettingsResponse uIndexResponse = getAdminClient().prepareUpdateSettings(indexName)//
.setSettings(settings)//
.execute().actionGet();
return uIndexResponse.isAcknowledged();
}
    /**
* 修改索引,修改索引的setting。
*
* @param indexName
* 索引名称<br>
* 如果不需要实时精确的查询结果,可以把每个索引的index.refresh_interval设置为30s,如果在导入大量的数据,可以把这个值先设置为-1,完成数据导入之后在设置回来<br>
* 如果在用bulk导入大量的数据,可以考虑不要副本,设置index.number_of_replicas:
* 0。有副本存在的时候,导入数据需要同步到副本,并且副本也要完成分析,索引和段合并的操作,影响导入性能。可以不设置副本导入数据然后在恢复副本。<br>
* <b>注意</b>:<br>
* 有些属性一旦创建就不可以修改,比如:index.number_of_shards,修改会抛出异常。
*/
public static boolean indexUpdateSettings(String indexName) {
Settings settings = Settings.builder() //
// .put("index.mapping.ignore_malformed", false)//
.put("index.refresh_interval", "30s") //
// .put("index.number_of_shards", 4)//
.put("index.number_of_replicas", 1)//
// .put("index.max_result_window", 500000)//
//
// .put("index.translog.durability", "async")//
// .put("index.translog.sync_interval", "120s")//
// .put("index.translog.flush_threshold_size", "2gb")//
//
.put("index.merge.scheduler.max_thread_count", 1)//
.build();
return indexUpdatSettings(indexName, settings);
}

ES API之Delete/Open/Close Index:

    /**
* 删除ES中某个或者多个索引
* */
public static boolean indexDelete(String... indices) {
DeleteIndexResponse dIndexResponse = getAdminClient().prepareDelete(indices).execute().actionGet();
if (dIndexResponse.isAcknowledged()) {
System.out.println("删除索引成功");
return true;
} else {
System.out.println("删除索引失败");
return false;
}
} /**
* 关闭ES中某个或者多个索引<br>
* curl -XPOST "http://127.0.0.1:9200/indexname/_close"
* */
public static boolean indexClose(String... indices) {
CloseIndexResponse cIndexResponse = getAdminClient().prepareClose(indices).execute().actionGet();
if (cIndexResponse.isAcknowledged()) {
System.out.println("关闭索引成功");
return true;
}
return false;
} /**
* 开启ES中某个或者多个索引<br>
* curl -XPOST "http://127.0.0.1:9200/indexname/_open"
* */
public static boolean indexOpen(String... indices) {
OpenIndexResponse oIndexResponse = getAdminClient().prepareOpen(indices).execute().actionGet();
if (oIndexResponse.isAcknowledged()) {
System.out.println("开启索引成功");
return true;
}
return false;
}

Spark2.2+ES6.4.2(三十二):ES API之index的create/update/delete/open/close(创建index时设置setting,并创建index后根据avro模板动态设置index的mapping)的更多相关文章

  1. SQL注入之Sqli-labs系列第三十二关(基于宽字符逃逸注入)

    开始挑战第三十二关(Bypass addslashes) 0x1查看源代码 (1)代码关键点 很明显,代码中利用正则匹配将 [ /,'," ]这些三个符号都过滤掉了 function che ...

  2. 《手把手教你》系列技巧篇(三十二)-java+ selenium自动化测试-select 下拉框(详解教程)

    1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助. 2.select 下拉框 2.1Select ...

  3. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

  4. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  5. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. 三十二、Java图形化界面设计——布局管理器之CardLayout(卡片布局)

    摘自 http://blog.csdn.net/liujun13579/article/details/7773945 三十二.Java图形化界面设计--布局管理器之CardLayout(卡片布局) ...

  7. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

  8. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  9. Gradle 1.12用户指南翻译——第三十二章. JDepend 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

随机推荐

  1. python 全栈开发,Day24(复习,__str__和__repr__,__format__,__call__,__eq__,__del__,__new__,item系列)

    反射: 使用字符串数据类型的变量名来使用变量 wwwh即what,where,why,how  这4点是一种学习方法 反射 :使用字符串数据类型的变量名来使用变量 1.文件中存储的都是字符串 2.网络 ...

  2. windows系统下ruby开发环境的搭建方法

    ruby是一种简单快捷的面向对象的脚本语言,非常直观.下面说一下windows系统下ruby开发环境的搭建方法. 工具/原料 rubyinstaller.exe 方法/步骤 1 到如下网站去下载最新的 ...

  3. bootstrap 全局样式设置

    HTML <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" co ...

  4. poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)

    左边的数字是1 2 3 4 5.... 右边的数字 第一个输入的和1连 第2个输入的和2连 右边再按从小到大排序 要求连线不能交叉 问最多能有多少条不交叉的线 假如右边有5个1 那么答案会是5 所以是 ...

  5. POJ 1862 Stripies 【优先队列】

    题意:科学家发现一种奇怪的东西,他们有重量weight,如果他们碰在一起,总重变成2*sqrt(m1*m2).要求出最终的重量的最小值. 思路:每次选取质量m最大的两个stripy进行碰撞结合,能够得 ...

  6. 结构型模式之Adapter模式

    适配器模式把一个类的接口变换成客户端所期待的另一种接口. 在JDK中的体现 把一个接口或类变成另外一种. java.util.Arrays#asList()javax.swing.JTable(Tab ...

  7. BZOJ 3994: [SDOI2015]约数个数和3994: [SDOI2015]约数个数和 莫比乌斯反演

    https://www.lydsy.com/JudgeOnline/problem.php?id=3994 https://blog.csdn.net/qq_36808030/article/deta ...

  8. 5.27 Test

    1.COGS.2039. 树的统计 思路: 各种方法. 代码: 1.遍历树1   时间 0.314 s   平均内存 2.96 MB #include<cstdio> using name ...

  9. BZOJ.3064.CPU监控(线段树 历史最值)

    题目链接 \(Description\) 有一个长为n的序列Ai,要求支持查询[l,r]的最值.历史最值,区间加/重设 \(Solution\) 线段树,每个点再维护一个历史(从0到现在)最大值.历史 ...

  10. Python3高级基础(2)

    1 Python3模拟数据结构 1.1 栈 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表.栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进 ...