主頁 > 軟體設計 > 【原來那么簡單/大資料】隨隨便便開發一個屬于自己的搜索引擎

【原來那么簡單/大資料】隨隨便便開發一個屬于自己的搜索引擎

2021-04-04 13:45:27 軟體設計

【1K資料集+SpringBoot+Thymeleaf】基于全文檢索技術lucene開發的搜索引擎

? 小編最近寫的專案=============》有問題咨詢可以加小哥微信:JL1714873054,如果覺得不錯可以點一波關注,謝謝,后臺看到私信一定會回復,沒有回復請諒解,可以關注我的微信公眾號:CodeLinghu ,預約畢設,預約專案,查看精彩的專案博客分享,

一、需求分析

  • 實作一個搜索框,能夠索引指定資料集(資料取自資料庫中)
  • 實作索引內容的展示,圖片展示
  • 實作文本分類,排序等基礎功能
  • 索引資料量>1K (可自行爬取)
  • 每次完成搜索能夠進行一次評價一次檢索效率
  • 可做畢設/可做專案/大創

1.1、專案效果圖展示

1.1.1前端頁面展示:


1.1.2資料庫資料展示:

二、所用技術堆疊

  1. SpringBoot
  2. Thymeleaf模板渲染
  3. mysql
  4. ik中文分詞
  5. lucene 索引
  6. json轉換
  7. HTML+CSS+JavaScript

2.1專案版本資訊:

  1. jdk1.8
  2. mysql 5.7.29
  3. lucene 7.7.2
  4. maven 3.6.3
  5. Windows 10系統
  6. IntellJ IDEA 2019 2.14
  7. Navicat for mysql 12.1.2

三、專案技術理論基礎篇

本專案的重點是搜索/索引,所以我們首先認識一下所謂的搜索功能,

傳統的搜索功能流程如圖01-00.

? 圖01-00

以上搜索功能是目前企業中較為傳統的一種搜索方式,其特點就是資料量少,承載不了高并發,

本專案所采用的搜索理論基礎方案如圖01-01.

? 圖01-01

使用新方案的優勢:

  1. 降低了資料庫壓力
  2. 提升了資料庫訪問速度
  3. 通過lucene的API操作索引庫訪問資料庫實作了業務與資料的有效隔離

資料查詢有兩種方案:

  • 順序查詢

所謂順序查詢就是通過用戶檢索的內容進行字串匹配,遍歷所有的檔案,當匹配到相同字串便查詢到當前檔案,沒有查到則繼續掃描下一個檔案,直到掃描完成所有檔案,

  • 倒排索引

倒排索引是指先將海量資料進行分詞,形成一個索引表,查詢時先查詢索引表,通過索引表查詢指定檔案,這樣可以做到有效去重查詢相同內容文本的時間,為了做到倒排索引,我們才用的則是全文檢索技術------lucene

3.1、Lucene相關認識(需要你認識到)

  1. lucene是一種技術架構,不是一個成型的技術產品,而是半產品,
  2. lucene是一個工具包,我們可以利用它完成索引工具的開發,制作屬于自己的搜索引擎產品
  3. Lucene在Java開發環境里是一個免費成熟的源代碼工具
  4. Lucene可以通過官方網站下載,當然我也會提供下載包鏈接()
  5. Lucene是Apache公司的產品
  6. Lucene實作全文檢索的基本流程圖:

  • 原始檔案資料:

    • 可以自行爬取資料,也可以用小哥提供的檔案資料
    • 檔案資料放在小哥配套的檔案夾(DataSources)里,是一個mysql檔案,大家可以直接匯入mysql即可,
  • 檔案:

    • 拿到原始檔案資料是為了建立索引,在索引前需要將原始內容創建文當 Document檔案 Document中包含了許多 Field

  • 分析檔案(分詞):

    分析檔案就是分詞,將檔案中的內容進行詞組劃分,

  • 索引檔案:

    索引檔案是為了更好地搜索,分詞形成了詞匯單元,通過索引詞匯單元快速找到需要被索引到的內容,

四、專案實戰篇

4.1 Lucene的下載

可以通過官方網站下載lucene,也可以在小哥留的資料包里下載

解壓后:

PS:queryparser:查詢決議器

使用以上三個檔案就可以實作本次專案中Lucene的功能,

4.2資料源下載

也在這個檔案夾下面:

匯入到mysql的效果:

4.3Java工程的創建

使用 DAO介面實作類獲取mysql中的資料:

package cn.linghu.dao;

import cn.linghu.pojo.Sku;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
public class SkuDaoImpl implements SkuDao {

    public List<Sku> querySkuList() {
        // 資料庫鏈接
        Connection connection = null;
        // 預編譯statement
        PreparedStatement preparedStatement = null;
        // 結果集
        ResultSet resultSet = null;
        // 商品串列
        List<Sku> list = new ArrayList<Sku>();

        try {
            // 加載資料庫驅動
            Class.forName("com.mysql.jdbc.Driver");
            // 連接資料庫
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/lucene", "root", "123456");

            // SQL陳述句
            String sql = "SELECT * FROM tb_sku";
            // 創建preparedStatement
            preparedStatement = connection.prepareStatement(sql);
            // 獲取結果集
            resultSet = preparedStatement.executeQuery();
            // 結果集決議
            while (resultSet.next()) {
                Sku sku = new Sku();
                sku.setId(resultSet.getString("id"));
                sku.setName(resultSet.getString("name"));
                sku.setSpec(resultSet.getString("spec"));
                sku.setBrandName(resultSet.getString("brand_name"));
                sku.setCategoryName(resultSet.getString("category_name"));
                sku.setImage(resultSet.getString("image"));
                sku.setNum(resultSet.getInt("num"));
                sku.setPrice(resultSet.getInt("price"));
                sku.setSaleNum(resultSet.getInt("sale_num"));
                list.add(sku);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }
}

4.3.1核心代碼------實作索引流程:

\1. 采集資料

\2. 創建Document檔案物件

\3. 創建分析器(分詞器)

\4. 創建IndexWriterConfifig配置資訊類

\5. 創建Directory物件,宣告索引庫存盤位置

\6. 創建IndexWriter寫入物件

\7. 把Document寫入到索引庫中

\8. 釋放資源
    
package cn.linghu.test;

import cn.linghu.dao.SkuDao;
import cn.linghu.dao.SkuDaoImpl;
import cn.linghu.pojo.Sku;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.MMapDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 索引庫維護
 */
public class TestIndexManager {


    /**
     * 創建索引庫
     */
    @Test
    public void createIndexTest() throws Exception {
        //1. 采集資料
        SkuDao skuDao = new SkuDaoImpl();
        List<Sku> skuList = skuDao.querySkuList();

        //檔案集合
        List<Document> docList = new ArrayList<>();

        for (Sku sku : skuList) {
            //2. 創建檔案物件
            Document document = new Document();

            //創建域物件并且放入檔案物件中
            /**
             * 是否分詞: 否, 因為主鍵分詞后無意義
             * 是否索引: 是, 如果根據id主鍵查詢, 就必須索引
             * 是否存盤: 是, 因為主鍵id比較特殊, 可以確定唯一的一條資料, 在業務上一般有重要所用, 所以存盤
             *      存盤后, 才可以獲取到id具體的內容
             */
            document.add(new StringField("id", sku.getId(), Field.Store.YES));

            /**
             * 是否分詞: 是, 因為名稱欄位需要查詢, 并且分詞后有意義所以需要分詞
             * 是否索引: 是, 因為需要根據名稱欄位查詢
             * 是否存盤: 是, 因為頁面需要展示商品名稱, 所以需要存盤
             */
            document.add(new TextField("name", sku.getName(), Field.Store.YES));

            /**
             * 是否分詞: 是(因為lucene底層演算法規定, 如果根據價格范圍查詢, 必須分詞)
             * 是否索引: 是, 需要根據價格進行范圍查詢, 所以必須索引
             * 是否存盤: 是, 因為頁面需要展示價格
             */
            document.add(new IntPoint("price", sku.getPrice()));
            document.add(new StoredField("price", sku.getPrice()));

            /**
             * 是否分詞: 否, 因為不查詢, 所以不索引, 因為不索引所以不分詞
             * 是否索引: 否, 因為不需要根據圖片地址路徑查詢
             * 是否存盤: 是, 因為頁面需要展示商品圖片
             */
            document.add(new StoredField("image", sku.getImage()));

            /**
             * 是否分詞: 否, 因為分類是專有名詞, 是一個整體, 所以不分詞
             * 是否索引: 是, 因為需要根據分類查詢
             * 是否存盤: 是, 因為頁面需要展示分類
             */
            document.add(new StringField("categoryName", sku.getCategoryName(), Field.Store.YES));

            /**
             * 是否分詞: 否, 因為品牌是專有名詞, 是一個整體, 所以不分詞
             * 是否索引: 是, 因為需要根據品牌進行查詢
             * 是否存盤: 是, 因為頁面需要展示品牌
             */
            document.add(new StringField("brandName", sku.getBrandName(), Field.Store.YES));

            //將檔案物件放入到檔案集合中
            docList.add(document);
        }
        //3. 創建分詞器, StandardAnalyzer標準分詞器, 對英文分詞效果好, 對中文是單字分詞, 也就是一個字就認為是一個詞.
        Analyzer analyzer = new IKAnalyzer();
        //4. 創建Directory目錄物件, 目錄物件表示索引庫的位置
        Directory  dir = FSDirectory.open(Paths.get("E:\\dir"));
        //5. 創建IndexWriterConfig物件, 這個物件中指定切分詞使用的分詞器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 創建IndexWriter輸出流物件, 指定輸出的位置和使用的config初始化物件
        IndexWriter indexWriter = new IndexWriter(dir, config);
        //7. 寫入檔案到索引庫
        for (Document doc : docList) {
            indexWriter.addDocument(doc);
        }
        //8. 釋放資源
        indexWriter.close();
    }

    /**
     * 索引庫修改操作
     * @throws Exception
     */
    @Test
    public void updateIndexTest() throws Exception {
        //需要變更成的內容
        Document document = new Document();

        document.add(new StringField("id", "100000003145", Field.Store.YES));
        document.add(new TextField("name", "xxxx", Field.Store.YES));
        document.add(new IntPoint("price", 123));
        document.add(new StoredField("price", 123));
        document.add(new StoredField("image", "xxxx.jpg"));
        document.add(new StringField("categoryName", "手機", Field.Store.YES));
        document.add(new StringField("brandName", "華為", Field.Store.YES));


        //3. 創建分詞器, StandardAnalyzer標準分詞器, 對英文分詞效果好, 對中文是單字分詞, 也就是一個字就認為是一個詞.
        Analyzer analyzer = new StandardAnalyzer();
        //4. 創建Directory目錄物件, 目錄物件表示索引庫的位置
        Directory  dir = FSDirectory.open(Paths.get("E:\\dir"));
        //5. 創建IndexWriterConfig物件, 這個物件中指定切分詞使用的分詞器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 創建IndexWriter輸出流物件, 指定輸出的位置和使用的config初始化物件
        IndexWriter indexWriter = new IndexWriter(dir, config);


        //修改, 第一個引數: 修改條件, 第二個引數: 修改成的內容
        indexWriter.updateDocument(new Term("id", "100000003145"), document);

        //8. 釋放資源
        indexWriter.close();
    }

    /**
     * 測驗根據條件洗掉
     * @throws Exception
     */
    @Test
    public void deleteIndexTest() throws Exception {
        //3. 創建分詞器, StandardAnalyzer標準分詞器, 對英文分詞效果好, 對中文是單字分詞, 也就是一個字就認為是一個詞.
        Analyzer analyzer = new StandardAnalyzer();
        //4. 創建Directory目錄物件, 目錄物件表示索引庫的位置
        Directory  dir = FSDirectory.open(Paths.get("E:\\dir"));
        //5. 創建IndexWriterConfig物件, 這個物件中指定切分詞使用的分詞器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 創建IndexWriter輸出流物件, 指定輸出的位置和使用的config初始化物件
        IndexWriter indexWriter = new IndexWriter(dir, config);


        //測驗根據條件洗掉
        //indexWriter.deleteDocuments(new Term("id", "100000003145"));

        //測驗洗掉所有內容
        indexWriter.deleteAll();

        //8. 釋放資源
        indexWriter.close();
    }


    /**
     * 測驗創建索引速度優化
     * @throws Exception
     */
    @Test
    public void createIndexTest2() throws Exception {
        //1. 采集資料
        SkuDao skuDao = new SkuDaoImpl();
        List<Sku> skuList = skuDao.querySkuList();

        //檔案集合
        List<Document> docList = new ArrayList<>();

        for (Sku sku : skuList) {
            //2. 創建檔案物件
            Document document = new Document();
            document.add(new StringField("id", sku.getId(), Field.Store.YES));
            document.add(new TextField("name", sku.getName(), Field.Store.YES));
            document.add(new IntPoint("price", sku.getPrice()));
            document.add(new StoredField("price", sku.getPrice()));
            document.add(new StoredField("image", sku.getImage()));
            document.add(new StringField("categoryName", sku.getCategoryName(), Field.Store.YES));
            document.add(new StringField("brandName", sku.getBrandName(), Field.Store.YES));

            //將檔案物件放入到檔案集合中
            docList.add(document);
        }

        long start = System.currentTimeMillis();

        //3. 創建分詞器, StandardAnalyzer標準分詞器, 對英文分詞效果好, 對中文是單字分詞, 也就是一個字就認為是一個詞.
        Analyzer analyzer = new StandardAnalyzer();
        //4. 創建Directory目錄物件, 目錄物件表示索引庫的位置
        Directory  dir = FSDirectory.open(Paths.get("E:\\dir"));
        //5. 創建IndexWriterConfig物件, 這個物件中指定切分詞使用的分詞器
        /**
         * 沒有優化 小100萬條資料, 創建索引需要7725ms
         *
         */
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //設定在記憶體中多少個檔案向磁盤中批量寫入一次資料
        //如果設定的數字過大, 會過多消耗記憶體, 但是會提升寫入磁盤的速度
        //config.setMaxBufferedDocs(500000);
        //6. 創建IndexWriter輸出流物件, 指定輸出的位置和使用的config初始化物件
        IndexWriter indexWriter = new IndexWriter(dir, config);
        //設定多少給檔案合并成一個段檔案,數值越大索引速度越快, 搜索速度越慢;  值越小索引速度越慢, 搜索速度越快
        //indexWriter.forceMerge(1000000);
        //7. 寫入檔案到索引庫
        for (Document doc : docList) {
            indexWriter.addDocument(doc);
        }
        //8. 釋放資源
        indexWriter.close();
        long end = System.currentTimeMillis();
        System.out.println("=====消耗的時間為:==========" + (end - start) + "ms");
    }

}

在E盤創建一個檔案夾名為 dir作為我們的索引檔案目錄,執行代碼成功之后, dir檔案夾內會出現如圖:

出現此圖表示創建索引成功!

4.3.2pom檔案中的依賴引入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.linghu</groupId>
    <artifactId>luceneDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <skipTests>true</skipTests>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>7.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>7.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>7.7.2</version>
        </dependency>

        <!-- 測驗 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- mysql資料庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <!-- IK中文分詞器 -->
      <!--  <dependency>
            <groupId>org.wltea.ik-analyzer</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>8.1.0</version>
        </dependency>-->

        <!--web起步依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Json轉換工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.51</version>
        </dependency>
    </dependencies>

</project>

后期還會進行專案總結,敬請期待,感謝支持!

  • 跑專案之前需要在E盤建立一個dir檔案夾
  • 需要配置好資料庫的資訊/賬戶/密碼
  • 需要引入或匯入相關的jar包

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/272209.html

標籤:其他

上一篇:MySQL學習總結-基礎架構概述

下一篇:SpringBoot---(4) Spring Boot 集成SSM框架和Dubbo分布式框架

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more