public class SimpleStringInterner extends StringInterner
可看出SimpleStringInterner提供一个简单的字符串引用缓存,节约内存,保证同一值的字符串使用同一段内存空间,因为使用了intern,所以继承自StringInterner
package org.apache.lucene.util;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Simple lockless and memory barrier free String intern cache that is guaranteed
* to return the same String instance as String.intern()
* does.
*
* @lucene.internal
*/
public class SimpleStringInterner extends StringInterner {
private static class Entry {
final private String str;
final private int hash;
private Entry next;
private Entry(String str, int hash, Entry next) {
this.str = str;
this.hash = hash;
this.next = next;
}
}
private final Entry[] cache;
private final int maxChainLength;
/ **
** param tableSize Size of the hash table, should be a power of two. tableSize
* * @param maxChaingenth Maximum length of each bucket, after which the oldest item inserted is dropped.
*/
public SimpleStringInterner(int tableSize, int maxChainLength) {
cache = new Entry[Math.max(1,BitUtil.nextHighestPowerOfTwo(tableSize))];
this.maxChainLength = Math.max(2,maxChainLength);
}
@Override
public String intern(String s) {
int h = s.hashCode();
// In the future, it may be worth augmenting the string hash
// if the lower bits need better distribution.
int slot = h & (cache.length-1);
Entry first = this.cache[slot];
Entry nextToLast = null;
int chainLength = 0;
for(Entry e=first; e!=null; e=e.next) {
if (e.hash == h && (e.str == s || e.str.compareTo(s)==0)) {
// if (e.str == s || (e.hash == h && e.str.compareTo(s)==0)) {
return e.str;
}
chainLength++;
if (e.next != null) {
nextToLast = e;
}
}
// insertion-order cache: add new entry at head
s = s.intern();
this.cache[slot] = new Entry(s, h, first);
if (chainLength >= maxChainLength) {
// prune last entry
nextToLast.next = null;
}
return s;
}
}
分析
1)构造了一个链表,每个元素为Entry对象,存储了元素的字符串格式的值、
哈希值以及下一个元素
private static class Entry {
final private String str;
final private int hash;
private Entry next;
private Entry(String str, int hash, Entry next) {
this.str = str;
this.hash = hash;
this.next = next;
}
}
2)定义了一个cache,实质为一个Entry对象组成的数组,同时包括最大的
长度maxChainLength
private final Entry[] cache;
private final int maxChainLength;
/**
* @param tableSize Size of the hash table, should be a power of two.
* @param maxChainLength Maximum length of each bucket, after which the oldest item inserted is dropped.
*/
3) SimpleStringInterner完成缓存区的建立与申请,其中 tableSize是
哈希表的大小, 且以2为倍数,maxChainlenth表示元素的最大数量 ,
且大于或等于2
public SimpleStringInterner(int tableSize, int maxChainLength) {
cache = new Entry[Math.max(1,BitUtil.nextHighestPowerOfTwo(tableSize))];
this.maxChainLength = Math.max(2,maxChainLength);
}
4)
A)
关于@Override
@override有注释文档的作用,可有可无有点像鸡肋
但它对于编程粗心的人可是个很人性化的功能
如果想重写父类的方法,比如toString()方法的话,在被重载的方法前面加上@Override ,这样编译的时候系统可以帮你检查方法的正确性
如下
@Override
public String toString(){...}这是正确的
如果将toString写成tostring
@Override
public String tostring(){...}编译器可以检测出这种写法是错误的,提醒你改正
而如果不加@Override
public String tostring(){...}这样编译器是不会报错的,它会认为是你在类中加的新方法
B)重载StringInterner的intern方法,s.hashCode()调用了String类的哈希方法
Java String类提供hashCode() 方法:
public int hashCode()返回int型(32位)
计算方式为:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
空字符串的hash值为0
例如,"FB" 和"Ea"有相同的hash值:
70 × 31 + 66 = 69 × 31 + 97
注意^表示按位异或
下面代码首先会计算出字符串的hash值,然后根据hash值在缓存中找到相应位置,可能会
发生多个不同字符串具有同一hash值的情况,因此将这些具有相同hash值的字符串各自组成
链表;然后在链表中找到相关位置,如果找到则返回,无法找到,则增加一个新的节点加入到
链表中,一个比较典型hash桶算法
@Override
public String intern(String s) {
int h = s.hashCode();
// In the future, it may be worth augmenting the string hash
// if the lower bits need better distribution.
//slot为在缓存中的位置
int slot = h & (cache.length-1);
//找到第一个适合的位置first,注意考虑到不同字符串的hash值相同,因此如果位置已经占用,必须通过e=e.next找到下一个可放置的位置
Entry first = this.cache[slot];
Entry nextToLast = null;
int chainLength = 0;
//将具有该HASH值的位置做为链表头开始,沿着链表寻找,
for(Entry e=first; e!=null; e=e.next) {
//如果字符串已经在缓存中存在,直接返回其值
if (e.hash == h && (e.str == s || e.str.compareTo(s)==0)) {
// if (e.str == s || (e.hash == h && e.str.compareTo(s)==0)) {
return e.str;
}
chainLength++;
//下一位置已经被占用,则将nextToLast标记为当前位置
if (e.next != null) {
nextToLast = e;
}
//沿着链表继续寻找字符串,找到了返回该字符串,到链表尾仍找不到,e将等于null,进入下一步,构造一个新的节点,将该节点加入链表中
}
// insertion-order cache: add new entry at head
// 构造一个链表中新节点的值,hash和 next(下一个链接):
new Entry(s, h, first);
将找到的由相同hash值组成的链表的首部做为新节点的next,就是说
将新节点插入到链表首部
// insertion-order cache: add new entry at head
s = s.intern();
this.cache[slot] = new Entry(s, h, first);
if (chainLength >= maxChainLength) {
// prune last entry
nextToLast.next = null;
}
return s;
分享到:
相关推荐
本压缩包包含的是Lucene 3.5.0版本的全部源码,对于想要深入理解Lucene工作原理、进行二次开发或者进行搜索引擎相关研究的开发者来说,是一份非常宝贵的学习资源。 Lucene 3.5.0是Lucene的一个重要版本,它在3.x...
在3.5版本中,Lucene 提供了多种功能,使得开发者能够轻松地在应用程序中集成搜索功能。这个压缩包包含了Lucene 3.5版本的一些关键组件,如中文分词器、核心包和高亮包等,这些对于构建高效、精确的文本搜索系统至关...
《深入理解Lucene 3.5:官网源代码解析》 Lucene,作为一个开源全文搜索引擎库,被广泛应用于各类信息检索系统中。它的3.5版本是其发展历程中的一个重要里程碑,提供了强大的搜索功能和高效的索引机制。在这个版本...
lucene3.5 IKAnalyzer3.2.5 实例中文分词通过,目前在网上找的lucene 和IKAnalyzer 的最新版本测试通过。内含:示例代码,以及最新jar包。 lucene lucene3.5 IKAnalyzer IKAnalyzer3.2.5 jar 中文 分词
luke3.5 可查看lucene3.5索引
《Lucene 3.5:创建、增删改查详解》 Lucene 是一个高性能、全文本搜索库,被广泛应用于各种搜索引擎的开发。在3.5版本中,Lucene 提供了强大的文本分析和索引功能,以及对文档的高效检索。本文将详细介绍如何在...
本篇文章将围绕“lucene3.5全文检索案例lucene+demo”,详细讲解Lucene 3.5的核心概念、关键功能以及如何通过实例进行操作。 一、Lucene 3.5核心概念 1. 文档(Document):Lucene中的最小处理单元,相当于数据库...
《Lucene3.5实例详解:构建全文搜索引擎》 Apache Lucene是一个开源的全文检索库,为Java开发者提供了强大的文本搜索功能。在本实例中,我们将深入探讨如何使用Lucene 3.5版本来构建一个基本的全文搜索引擎,主要...
lucene3.5高亮
**Lucene 3.5 API 概述** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发。它提供了高级文本检索功能,广泛用于构建搜索引擎和其他需要高效全文检索能力的应用。Lucene 3.5 API 是该库在2011年发布...
《Lucene 3.5中文分词案例解析》 Lucene是一个开源的全文搜索引擎库,广泛应用于各种信息检索系统中。在3.5版本中,Lucene已经支持了中文分词,这对于处理中文文档和搜索需求显得尤为重要。本文将深入探讨Lucene ...
chm格式的Lucene帮助文档,Lucene3.5
《深入探索Lucene 3.5:学习研究报告》 Lucene 3.5是一个重要的版本更新,它在2011年11月26日发布,为搜索引擎开发者提供了更高效、更稳定的功能。该版本在性能优化、新特性和错误修复上取得了显著的进步。 首先,...
《深入剖析Lucene 3.5源码:揭示搜索...总结,Lucene 3.5的源码是一份宝贵的资源,它揭示了搜索引擎技术的复杂性和精妙之处。无论是初学者还是经验丰富的开发者,都能从中受益匪浅,提升对全文检索和搜索引擎的理解。
《Lucene 3.5 学习笔记》 在信息技术高速发展的今天,搜索引擎技术成为了信息检索的核心工具。Apache Lucene,作为一个开源全文检索库,为开发者提供了强大的文本搜索功能。本文将深入探讨Lucene 3.5版本的相关知识...
在本文中,我们将深入探讨 Lucene 3.5 API,这是一个相对早期但仍然具有重要参考价值的版本。 ### 一、Lucene 的核心组件 1. **Analyzer**: 分析器是 Lucene 的关键组件,负责将输入的文本分解成可索引的词元...
在“关于lucene3.5的使用”这个主题中,我们将深入探讨Lucene 3.5的关键特性、核心组件以及如何通过实例进行应用。首先,我们需要了解以下几个核心概念: 1. **索引(Index)**:Lucene 的工作基于索引,就像书籍的...
在本篇文章中,我们将深入探讨 Lucene 3.5 版本的 API,尽管它是英文版,但其丰富的功能和详细文档使其对开发者极具价值。 1. **Lucene 的基本概念** - **索引(Index)**:Lucene 使用倒排索引(Inverted Index)...
solr_lucene3.5_lukeall-3.5.0.jar.zip
Lucene3.5视频教程(内含分享链接) 一共50集, 包含各部分讲解及源码