Java 单链表数据结构的增删改查教程
我就废话不多说了,大家还是直接看代码吧~
package链表;
/**
*
*1)单链表的插入、删除、查找操作;
*2)链表中存储的是int类型的数据;
**/
publicclassSinglyLinkedList{
privateNodehead=null;
//查找操作
publicNodefindByValue(intvalue){
Nodep=head;//从链表头部开始查找
while(p.next!=null&&p.data!=value){//如果数据不相等并且下一个节点不为null,继续查找
p=p.next;
}
returnp;
}
//通过index查找
publicNodefindByIndex(intindex){
Nodep=head;//从链表头部开始查找
intcount=0;//指针计数器
while(p.next!=null&&index!=count){//当下个节点不为null,并且计数器不等于index的时候继续查找
p=p.next;
count++;
}
returnp;
}
//无头部节点(哨兵),表头部插入一个值,这种操作和输入的顺序相反,逆序
publicvoidinsertToHead(intvalue){
NodenewNode=newNode(value,null);
insertToHead(newNode);
}
//无头部节点(哨兵),表头部插入新节点,这种操作和输入的顺序相反,逆序
publicvoidinsertToHead(NodenewNode){
if(head==null){
head=newNode;
}else{
newNode.next=head;
head=newNode;
}
}
//链表尾部插入,按顺序插入,时间复杂度平均为O(n),这个可以优化,定义多一个尾部节点,不存储任何数据,时间复杂度未O(1)
publicvoidinsertTail(intvalue){
NodenewNode=newNode(value,null);
if(head==null){//链表为空
head=newNode;
}else{//直接从链表头开始找,知道找到链尾节点
Nodecurr=head;
while(curr.next!=null){
curr=curr.next;
}
curr.next=newNode;
}
}
//在指定节点后面插入新节点,直接在这个节点后面断开连接,直接插入
publicvoidinsertAfter(Nodep,intvalue){
NodenewNode=newNode(value,null);
insertAfter(p,newNode);
}
//在指定节点后面插入新节点,直接在这个节点后面断开连接,直接插入
publicvoidinsertAfter(Nodep,NodenewNode){
if(p==null){
return;
}
newNode.next=p.next;
p.next=newNode;
}
//在指定节点前面插入新节点
publicvoidinsertBefore(Nodep,intvalue){
NodenewNode=newNode(value,null);
insertBefore(p,newNode);
}
//在指定节点前面插入新节点
publicvoidinsertBefore(Nodep,NodenewNode){
if(p==null){
return;
}
if(p==head){//如果指定节点是头节点
insertToHead(p);
return;
}
Nodecurr=head;//当前节点,(查找指定节点p的前一个节点,当curr的下个节点等于指定节点时候,curr就是指定节点的前一个节点
while(curr!=null&&curr.next!=p){//当前节点不为null,当前节点的下个节点不等于指点节点,则继续查找
curr=curr.next;
}
if(curr==null){//未找到指定节点p
return;
}
newNode.next=p;
curr.next=newNode;
}
//删除指定节点
publicvoiddeleteByNode(Nodep){
if(p==null||p==head){
return;
}
Nodecurr=head;//从链头开始查找,curr是当前节点,查找指定节点p的前一个节点,当curr的下个节点等于指定节点时候,curr就是指定节点的前一个节点
while(curr!=null&&curr.next!=p){//当前节点不为null并且,下个节点不等于指定节点时候继续查找
curr=curr.next;
}
if(curr==null){//未找到指定节点
return;
}
curr.next=curr.next.next;
}
//删除指定值
publicvoiddeleteByValue(intvalue){
if(head==null){
return;
}
Nodecurr=head;//当前节点,从链表头开始查找
Nodepre=null;//当前节点的前一个节点,找查找指定的过程,要不断地保存当前节点的前一个节点
while(curr!=null&&curr.data!=value){
pre=curr;
curr=curr.next;
}
if(curr==null){//未找到指定的值
return;
}
if(pre==null){//链表头数据就是指定的值
head=head.next;
}else{
pre.next=pre.next.next;//或者pre.next=curr.next;
}
}
//打印链表
publicvoidprintAll(){
Nodecurr=head;
while(curr!=null){
System.out.println(curr.data);
curr=curr.next;
}
}
//单链表数据结构类,以存储int类型数据为例
publicclassNode{
privateintdata;
privateNodenext;
publicNode(intdata,Nodenext){
this.data=data;
this.next=next;
}
publicintgetData(){
returndata;
}
}
publicstaticvoidmain(String[]args){
老师代码.linkedlist06.SinglyLinkedListlink=new老师代码.linkedlist06.SinglyLinkedList();
System.out.println("hello");
intdata[]={1,2,5,3,1};
for(inti=0;i
补充知识:Hbase+SpringAop配置Hbase链接的开启和关闭
Spring提供了HbaseTemplate对Hbase数据库的常规操作进行了简单的封装。
get,find方法分别对应了单行数据查询和list查询。
这些查询都要开启和关闭Hbase数据库链接
@Override
publicTexecute(StringtableName,TableCallbackaction){
Assert.notNull(action,"Callbackobjectmustnotbenull");
Assert.notNull(tableName,"Notablespecified");
HTableInterfacetable=getTable(tableName);
try{
booleanpreviousFlushSetting=applyFlushSetting(table);
Tresult=action.doInTable(table);
flushIfNecessary(table,previousFlushSetting);
returnresult;
}catch(Throwableth){
if(thinstanceofError){
throw((Error)th);
}
if(thinstanceofRuntimeException){
throw((RuntimeException)th);
}
throwconvertHbaseAccessException((Exception)th);
}finally{
releaseTable(tableName,table);
}
}
privateHTableInterfacegetTable(StringtableName){
returnHbaseUtils.getHTable(tableName,getConfiguration(),getCharset(),getTableFactory());
}
privatevoidreleaseTable(StringtableName,HTableInterfacetable){
HbaseUtils.releaseTable(tableName,table,getTableFactory());
}
HTableInterfacetable=getTable(tableName);获取数据库链接
releaseTable(tableName,table);释放链接
在HbaseUtils.getHTable:
if(HbaseSynchronizationManager.hasResource(tableName)){
return(HTable)HbaseSynchronizationManager.getResource(tableName);
}
看见这个大家应该都有是曾相似的感觉吧,这和Spring事务管理核心类TransactionSynchronizationManager很像,而实现也基本一样
都是通过ThreadLocal将链接保存到当前线程中。
我们要做的就是要像Srping事务配置一样,在进入service方法时通过Aop机制将tableNames对应的链接加入到线程中。
Spring提供了这个Aop方法拦截器HbaseInterceptor:
publicObjectinvoke(MethodInvocationmethodInvocation)throwsThrowable{
SetboundTables=newLinkedHashSet();
for(StringtableName:tableNames){
if(!HbaseSynchronizationManager.hasResource(tableName)){
boundTables.add(tableName);
HTableInterfacetable=HbaseUtils.getHTable(tableName,getConfiguration(),getCharset(),getTableFactory());
HbaseSynchronizationManager.bindResource(tableName,table);
}
}
try{
ObjectretVal=methodInvocation.proceed();
returnretVal;
}catch(Exceptionex){
if(this.exceptionConversionEnabled){
throwconvertHBaseException(ex);
}
else{
throwex;
}
}finally{
for(StringtableName:boundTables){
HTableInterfacetable=(HTableInterface)HbaseSynchronizationManager.unbindResourceIfPossible(tableName);
if(table!=null){
HbaseUtils.releaseTable(tableName,table);
}
else{
log.warn("Table["+tableName+"]unboundfromthethreadbysomebodyelse;cannotguaranteeproperclean-up");
}
}
}
}
很明显在
ObjectretVal=methodInvocation.proceed();
也就是我们的service方法执行前去获取Hbase链接并通过HbaseSynchronizationManager.bindResource(tableName,table);绑定到线程中。
finally中releaseTable。
Aop配置如下:
table_name1
table_name2
Hbase的数据库表链接跟传统数据库不太一样,开启链接必需要表名,所以HbaseInterceptor中必需设置privateString[]tableNames;
在进入servcie方法时,tableNames中对应的表链接都会开启。这必然会造成浪费,因为并不是每个service都会把表都查询一遍。
以上这篇Java单链表数据结构的增删改查教程就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。