当前位置: 首页 > news >正文

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务

在现代应用程序中,全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统,还是数据分析平台,快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎库,它提供了高效的索引和搜索功能,能够轻松集成到Java应用程序中。本文将介绍如何使用Apache Lucene构建一个高效的全文搜索服务,并通过一个实际的Java代码示例来展示其核心功能。

1. Lucene简介

Apache Lucene 是一个高性能、全功能的文本搜索引擎库,使用Java编写。它提供了强大的索引和搜索功能,支持多种查询类型,如布尔查询、范围查询、模糊查询等。Lucene的核心优势在于其高效的索引结构和灵活的API,使得开发者可以轻松地构建复杂的搜索功能。

2. 项目结构

在这个示例中,我们将构建一个简单的搜索服务,用于索引和搜索拍卖交易历史记录(AtcoinDealhistory)。项目的主要类 LuceneService 负责管理索引的创建、更新和搜索操作。

3. 索引创建与更新

在Lucene中,索引的创建和更新是通过 IndexWriter 来完成的。IndexWriter 负责将文档(Document)添加到索引中,并确保索引的高效存储和检索。

public void indexDocument(List<AtcoinDealhistory> list) throws IOException {long startTime = System.currentTimeMillis(); // 记录开始时间// 配置IndexWriterIndexWriterConfig config = new IndexWriterConfig(analyzer);config.setMaxBufferedDocs(20); // 设置最大缓冲文档数config.setRAMBufferSizeMB(2048.0); // 设置RAM缓冲区大小config.setUseCompoundFile(true); // 使用复合文件格式// 使用try-with-resources确保IndexWriter正确关闭try (IndexWriter indexWriter = new IndexWriter(directory, config)) {for (AtcoinDealhistory atcoinDealhistory : list) {Document doc = new Document();if (atcoinDealhistory.getAuctionId() != null) {// 添加字段到文档doc.add(new StringField("id", atcoinDealhistory.getId().toString(), Store.YES));doc.add(new StringField("auction_id", atcoinDealhistory.getAuctionId(), Store.YES));doc.add(new TextField("auction_name", atcoinDealhistory.getAuctionName(), Store.YES));doc.add(new StringField("amount", atcoinDealhistory.getAmount(), Store.YES));doc.add(new TextField("data", atcoinDealhistory.getData(), Store.YES));doc.add(new StringField("picture", atcoinDealhistory.getPicture(), Store.YES));// 处理日期字段if (atcoinDealhistory.getDealdate() != null) {try {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");String dateStr = dateFormat.format(atcoinDealhistory.getDealdate());// 添加日期字段,用于排序doc.add(new SortedNumericDocValuesField("date", atcoinDealhistory.getDealdate().getTime()));// 添加日期字段,用于存储doc.add(new StringField("dealdate", dateStr, Store.YES));} catch (Exception e) {e.printStackTrace();}}}// 将文档添加到索引indexWriter.addDocument(doc);indexWriter.commit(); // 提交更改}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis(); // 记录结束时间System.out.println("Index creation time: " + (endTime - startTime) + " milliseconds");
}

在这个方法中,我们首先配置了 IndexWriter,然后遍历 AtcoinDealhistory 对象列表,将每个对象的字段添加到 Document 中,并将其写入索引。我们还处理了日期字段,确保它们可以用于排序和存储。

4. 搜索功能

Lucene 的搜索功能是通过 IndexSearcher 来实现的。IndexSearcher 负责执行查询并返回匹配的文档。我们可以使用多种查询类型来构建复杂的搜索条件。

public List<AtcoinDealhistory> search(AtcoinDealhistory atcoinDealhistory) throws IOException, org.apache.lucene.queryparser.classic.ParseException {List<AtcoinDealhistory> results = new ArrayList<>();long startTime = System.currentTimeMillis(); // 记录开始时间// 打开索引目录try (DirectoryReader reader = DirectoryReader.open(directory)) {IndexSearcher searcher = new IndexSearcher(reader);BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();// 处理日期范围查询String startQueryDealDate = atcoinDealhistory.getStartQueryDealDate();String endQueryDealDate = atcoinDealhistory.getEndQueryDealDate();if (startQueryDealDate != null && endQueryDealDate != null) {TermRangeQuery dateRangeQuery = TermRangeQuery.newStringRange("dealdate", startQueryDealDate, endQueryDealDate, true, true);booleanQueryBuilder.add(dateRangeQuery, Occur.MUST);}// 处理金额范围查询Integer startQueryAmount = atcoinDealhistory.getStartQueryAmount();Integer endQueryAmount = atcoinDealhistory.getEndQueryAmount();if (startQueryAmount != null && endQueryAmount != null) {TermRangeQuery amountRangeQuery = TermRangeQuery.newStringRange("amount", Integer.toString(startQueryAmount), Integer.toString(endQueryAmount), true, true);booleanQueryBuilder.add(amountRangeQuery, Occur.MUST);}// 处理拍卖名称的关键词查询List<String> terms = analyzeQueryString(analyzer, atcoinDealhistory.getAuctionName());for (String term : terms) {TermQuery termQuery = new TermQuery(new Term("auction_name", term));booleanQueryBuilder.add(termQuery, Occur.MUST);}// 设置排序规则,根据日期字段降序排列SortField sortDate = new SortField("date", SortField.Type.LONG, true);Sort sort = new Sort(SortField.FIELD_SCORE, sortDate);// 执行查询ScoreDoc[] hits = searcher.search(booleanQueryBuilder.build(), 100, sort).scoreDocs;SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");// 遍历查询结果for (ScoreDoc hit : hits) {Document doc = searcher.doc(hit.doc);AtcoinDealhistory result = new AtcoinDealhistory();result.setId(Long.valueOf(doc.get("id")));result.setAuctionId(doc.get("auction_id"));result.setAuctionName(doc.get("auction_name"));result.setAmount(doc.get("amount"));result.setData(doc.get("data"));result.setPicture(doc.get("picture"));// 处理日期字段if (doc.get("dealdate") != null) {try {Date dealdate = dateFormat.parse(doc.get("dealdate"));result.setDealdate(dealdate);} catch (Exception e) {e.printStackTrace();}}results.add(result);}}long endTime = System.currentTimeMillis(); // 记录结束时间System.out.println("Index search time: " + (endTime - startTime) + " milliseconds");return results;
}

在这个方法中,我们首先打开索引目录并创建 IndexSearcher。然后,我们构建了一个布尔查询(BooleanQuery),用于处理日期范围、金额范围和关键词查询。最后,我们执行查询并遍历结果,将匹配的文档转换为 AtcoinDealhistory 对象并返回。

5. 分词器

Lucene 的分词器(Analyzer)用于将文本分解为单词或词语。在这个示例中,我们使用了 StandardAnalyzer,它是Lucene提供的一个标准分词器,适用于大多数英文文本。

	public LuceneService() throws IOException {// 索引目录的路径this.directory = FSDirectory.open(Paths.get(INDEX_DIR));// 标准索引解析器this.analyzer = new StandardAnalyzer();// 第三方分词器解析器
//		this.analyzer = new ReIKAnalyzer(false);}
public List<String> analyzeQueryString(Analyzer analyzer, String queryString) throws IOException {List<String> terms = new ArrayList<>();// 使用分词器处理查询字符串try (TokenStream tokenStream = analyzer.tokenStream("auction_name", new StringReader(queryString))) {CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);tokenStream.reset();// 遍历分词结果while (tokenStream.incrementToken()) {terms.add(charTermAttribute.toString());}tokenStream.end();}return terms;
}

这个方法将查询字符串分解为多个词语,并将它们添加到列表中,以便在搜索时使用。

6. 总结

通过这个示例,我们展示了如何使用Apache Lucene构建一个高效的全文搜索服务。Lucene提供了强大的索引和搜索功能,使得开发者可以轻松地处理复杂的搜索需求。无论是处理结构化数据还是非结构化文本,Lucene都能提供高效的解决方案。

7. 附录

maven 依赖

<!-- 搜索模块 --><!-- Lucene Core Dependency --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>8.11.0</version> <!-- 请根据需要选择合适的版本 --></dependency><!-- Lucene Analyzers Dependency --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>8.11.0</version></dependency><!-- 如果需要其他Lucene模块,也可以继续添加 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-highlighter</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-memory</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queries</artifactId><version>8.11.0</version></dependency><!-- <dependency><groupId>org.truenewx</groupId><artifactId>ik-analyzer-lucene</artifactId><version>5.0.1</version></dependency>--><dependency><groupId>com.github.keran213539</groupId><artifactId>IK_Analyzer</artifactId><version>2012FF_hf1_1</version></dependency><!-- https://mvnrepository.com/artifact/org.ansj/ansj_seg --><!-- <dependency><groupId>org.ansj</groupId><artifactId>ansj_seg</artifactId><version>5.1.6</version></dependency>-->

多线程索引创建

索引创建的时间有点久了,增加多线程处理

// 创建或更新索引public void indexDocument(List<AtcoinDealhistory> list) throws IOException {long startTime = System.currentTimeMillis(); // 记录开始时间//引入多线程ExecutorService executorService = Executors.newFixedThreadPool(numThreads);try {for (AtcoinDealhistory atcoinDealhistory : list) {executorService.submit(() -> {try {indexDocument(this.directory,this.analyzer,atcoinDealhistory);} catch (IOException e) {e.printStackTrace();}});}executorService.shutdown();executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);long endTime = System.currentTimeMillis(); // 记录结束时间// 计算索引创建时间long indexCreationTime = endTime - startTime;System.out.println("Index creation time: " + indexCreationTime/1000 + " milliseconds");} catch (Exception e) {System.out.println(e.getMessage());e.printStackTrace();} }

IK分词器重写

因为Lucene版本问题,IKAnalyzer 需要进行重写

package com.atcoin.busi.test;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
import org.wltea.analyzer.cfg.Configuration;public class ReIKAnalyzer extends Analyzer {private boolean useSmart;//分词器配置项private Configuration cfg;public Configuration getCfg() {return cfg;}public void setCfg(Configuration cfg) {this.cfg = cfg;}public boolean useSmart() {return useSmart;}public void setUseSmart(boolean useSmart) {this.useSmart = useSmart;}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** 默认细粒度切分算法*/public ReIKAnalyzer() {this(false);}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** @param useSmart*            当为true时,分词器进行智能切分*/public ReIKAnalyzer(boolean useSmart) {super();this.useSmart = useSmart;}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** @param cfg*/public ReIKAnalyzer(Configuration cfg) {super();this.setCfg(cfg);}/*** 重载Analyzer接口,构造分词组件** @param fieldName*            the name of the fields content passed to the*            TokenStreamComponents sink as a reader*/@Overrideprotected TokenStreamComponents createComponents(String fieldName) {Tokenizer _IKTokenizer = new ReIKTokenizer(this.useSmart());return new TokenStreamComponents(_IKTokenizer);}}
package com.atcoin.busi.test;
import java.io.IOException;import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;public class ReIKTokenizer extends Tokenizer {// IK分词器实现private IKSegmenter _IKImplement;// 词元文本属性private final CharTermAttribute termAtt;// 词元位移属性private final OffsetAttribute offsetAtt;// 词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)private final TypeAttribute typeAtt;// 记录最后一个词元的结束位置private int endPosition;/*** Lucene 5.4.0 Tokenizer适配器类构造函数** @param in* @param useSmart*/public ReIKTokenizer(boolean useSmart) {super();offsetAtt = addAttribute(OffsetAttribute.class);termAtt = addAttribute(CharTermAttribute.class);typeAtt = addAttribute(TypeAttribute.class);_IKImplement = new IKSegmenter(input, useSmart);}/*** Lucene 5.4.0 Tokenizer适配器类构造函数** @param in* @param cfg*/public ReIKTokenizer(Configuration cfg) {super();offsetAtt = addAttribute(OffsetAttribute.class);termAtt = addAttribute(CharTermAttribute.class);typeAtt = addAttribute(TypeAttribute.class);_IKImplement = new IKSegmenter(input, cfg);}@Overridepublic boolean incrementToken() throws IOException {// 清除所有的词元属性clearAttributes();Lexeme nextLexeme = _IKImplement.next();if (nextLexeme != null) {// 将Lexeme转成Attributes// 设置词元文本termAtt.append(nextLexeme.getLexemeText());// 设置词元长度termAtt.setLength(nextLexeme.getLength());// 设置词元位移offsetAtt.setOffset(nextLexeme.getBeginPosition(),nextLexeme.getEndPosition());// 记录分词的最后位置endPosition = nextLexeme.getEndPosition();// 记录词元分类typeAtt.setType(nextLexeme.getLexemeTypeString());// 返会true告知还有下个词元return true;}// 返会false告知词元输出完毕return false;}@Overridepublic void reset() throws IOException {super.reset();_IKImplement.reset(input);}@Overridepublic final void end() {// set final offsetint finalOffset = correctOffset(this.endPosition);offsetAtt.setOffset(finalOffset, finalOffset);}
}

接口调用

package com.atcoin.busi.controller;
import java.io.IOException;
import java.util.List;import javax.annotation.PreDestroy;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import com.atcoin.busi.domain.AtcoinDealhistory;
import com.atcoin.busi.service.IAtcoinDealhistoryService;
import com.atcoin.busi.service.impl.LuceneService;@RestController
@RequestMapping("/lucene")
public class AtcoinLuceneController {@Autowiredprivate IAtcoinDealhistoryService atcoinDealhistoryService;@Autowiredprivate LuceneService luceneService;//    @PostMapping("/index")
//    public String indexDocument(@RequestParam String id, @RequestParam String content) {
//        try {
//            luceneService.indexDocument(id, content);
//            return "Document indexed successfully.";
//        } catch (IOException e) {
//            e.printStackTrace();
//            return "Failed to index document.";
//        }
//    }@GetMapping("/createIndex")public String createIndex() {try {List<AtcoinDealhistory> list = atcoinDealhistoryService.selectAtcoinDealhistoryIndex();luceneService.indexDocument(list);return "Document indexed successfully.";} catch (IOException e) {e.printStackTrace();return "Failed to index document.";}}@GetMapping("/search")public List<AtcoinDealhistory> search(@RequestParam String keywords) {try {return luceneService.search(keywords);} catch (IOException | org.apache.lucene.queryparser.classic.ParseException e) {e.printStackTrace();return null;}}// 在应用关闭时关闭Lucene资源@PreDestroypublic void close() {try {luceneService.close();} catch (IOException e) {e.printStackTrace();}}
}

相关文章:

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中&#xff0c;全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统&#xff0c;还是数据分析平台&#xff0c;快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

SSH远程登录并执行命令

SSH远程登录并执行命令 1、登录远程服务器2、远程执行命令3、远程执行交互命令4、远程执行脚本5、退出远程SSH连接 SSH是Linux中的远程连接管理工具&#xff0c;可以在本地服务器上通过SSH协议连接到远程服务器&#xff0c;并在远程服务器上执行命令 SSH不仅可以用来登录远程服…...

EasyRTC:支持任意平台设备的嵌入式WebRTC实时音视频通信SDK解决方案

随着互联网技术的飞速发展&#xff0c;实时音视频通信已成为各行各业数字化转型的核心需求之一。无论是远程办公、在线教育、智慧医疗&#xff0c;还是智能安防、直播互动&#xff0c;用户对低延迟、高可靠、跨平台的音视频通信需求日益增长。 一、WebRTC与WebP2P&#xff1a;实…...

Golang语言特性

1.Go语言的优势 1.1极简单的部署方式 —可以直接编译成机器码。代码可以直接转换为二进制数据&#xff0c;在操作系统上可以直接./去执行。 —不依赖其他库。最终生成的可执行程序是一个静态的二进制文本文件。 —可以直接运行即可部署。 —静态类型语言。编译的时候检查出来隐…...

LangPrompt提示词

LangPrompt提示词 https://github.com/langgptai/LangGPT 学习LangGPT的仓库&#xff0c;帮我创建 一个专门生成LangGPT格式prompt的助手 根据LangGPT的格式规范设计的专业提示词生成助手框架。以下是分步骤的解决方案&#xff1a; 助手角色定义模板 # Role: LangGPT提示词架…...

Java 容器之 List

在 Java 的集合框架中&#xff0c;List 是 Collection 的重要子接口&#xff0c;以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类&#xff08;如 ArrayList 和 LinkedList&#xff09;的底层原理&#xff0c;以及使用中需要注意的常见问题…...

ETL-kettle数据转换使用详解

一、excel转换成mysql 表格就按照我们刚才转换的表格来转换成MySQL数据 在MySQL数据库中创建数据库&#xff0c;这个根据自身情况。我就在现有test库中测试了。 根据以上步骤&#xff0c;新建转换。 构建流程图&#xff0c;选择excel输入和表输出 将两个组件连接起来 双击…...

【容器化】低版本docker拉取ubuntn 22.04镜像启动容器执行apt update提示 NO_PUBKEY 871920D1991BC93C

前置信息 宿主机信息 [root@localhost ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR…...

Hive-04之存储格式、SerDe、企业级调优

一、主题 hive表的数据压缩和文件存储格式hive的自定义UDF函数hive的JDBC代码操作hive的SerDe介绍和使用hive的优化 二、要点 1. hive表的文件存储格式 Hive支持的存储数的格式主要有&#xff1a;TEXTFILE&#xff08;行式存储&#xff09; 、SEQUENCEFILE(行式存储)、ORC&…...

Makefile、Make和CMake:构建工具的三剑客

目录 1. Makefile 2. Make 3. CMake Makefile、Make、CMake的关系 在软件开发中&#xff0c;构建工具是必不可少的。它们帮助开发者自动化编译、链接和打包的过程&#xff0c;确保代码能够高效地转化为可执行文件。Makefile、Make和CMake是三个常见的构建工具&#xff0c;它…...

The “Rule-of-Zero“ should be followed (s4963)

Most classes should not directly handle resources, but instead, use members that perform resource handling for them: For memory, it can be std::unique_ptr, std::shared_ptr, std::vector…​For files, it can be std::ofstream, std::ifstream…​…​ Classes …...

Kotlin语言特性(二):泛型与注解

Kotlin语言特性(二):泛型与注解 一、引言 在上一篇文章中,我们介绍了Kotlin的三大核心特性。本文将深入探讨Kotlin的泛型和注解特性,并与Java进行对比,帮助你更好地理解和运用这些特性。 二、Kotlin泛型 2.1 泛型基础 2.1.1 声明泛型类 // Kotlin泛型类声明 class …...

FunPapers[3]:WWW‘25「快手」生成式回归预测观看时长

Sequence Generation Modeling for Continuous Value Prediction https://arxiv.org/pdf/2412.20211&#xff0c;www 2025. 文章目录 Sequence Generation Modeling for Continuous Value Prediction核心思想1. CVP常规方法是怎么做的&#xff1f;2. 观看时长预测和CVP是如何关…...

并发编程1

JAVA线程回顾 多线程 多个并行的线程来完成个自的任务&#xff0c;优点是程序响应速度更快&#xff0c;程序性能得到提升。 并行执行与并发执行 并发执行就是在单核CPU下&#xff0c;现成实际上是串行执行的&#xff0c;任务调度器将cpu的时间片分给不同的线程使用&#xff0…...

Hadoop之01:HDFS分布式文件系统

HDFS分布式文件系统 1.目标 理解分布式思想学会使用HDFS的常用命令掌握如何使用java api操作HDFS能独立描述HDFS三大组件namenode、secondarynamenode、datanode的作用理解并独立描述HDFS读写流程HDFS如何解决大量小文件存储问题 2. HDFS 2.1 HDFS是什么 HDFS是Hadoop中的一…...

从源到目标:深度学习中的迁移学习与领域自适应实践

云边有个稻草人-CSDN博客 目录 引言 一、迁移学习概述 1.1 迁移学习的类型 1.2 迁移学习的核心思想 1.3 迁移学习的应用场景 二、领域自适应&#xff08;Domain Adaptation&#xff09; 2.1 领域自适应的定义 2.2 领域自适应的挑战 2.3 领域自适应的核心方法 &#…...

WebRTC与PJSIP:呼叫中心系统技术选型指南

助力企业构建高效、灵活的通信解决方案 在数字化时代&#xff0c;呼叫中心系统的技术选型直接影响客户服务效率和业务扩展能力。WebRTC与PJSIP作为两大主流通信技术&#xff0c;各有其核心优势与适用场景。本文从功能、成本、开发门槛等维度为您深度解析&#xff0c;助您精准匹…...

使用IDEA如何隐藏文件或文件夹

选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹...

【人工智能】数据挖掘与应用题库(1-100)

1、涉及变化快慢的问题可以考虑使用导数来分析。 答案:对 2、导数的几何意义是曲线在某点处切线的斜率。 答案:对 3、函数在某点的左导数存在,则导数就存在。 答案:错 4、关于梯度下降算法,下列说法错误的是( ) 错误:梯度下降算法能找到函数精确的最小值。 5、正…...

腾讯云大模型知识引擎驱动的DeepSeek满血版医疗顾问大模型搭建实战

文章目录 1. 引言2. 什么是腾讯云大模型知识引擎&#xff08;LKE&#xff09;&#xff1f;核心优势功能特点应用场景 3. 模型搭建过程3.1 注册登录产品3.2 创建应用3.3 配置模型3.4 配置角色指令3.5 配置欢迎语3.6 配置知识库3.7 配置工作流3.8 启用联网搜索3.9 发布模型 4. 问…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...