今天昨天学了集合框架,但是在List接口下有两个子类涉及到了链表,书上又提到了一个关键的词“双向循环链表”,折腾了一整天终于搞懂了。
首先我们得明白什么是链表,链表是环环相扣的一组数据,而我们常用的数组就是一组顺序链表,在分配内存时内存将对数组分配一组”连续的内存空间“而这个内存空间是固定的是程序启动前就设定好的大小,但是这样做的弊端就是当对数组分配1000的内存空间若只用了很少的一部分多余的部分也会占用内存,但是单链表很好的解决了这一问题。
单链表
链表内部的存储实现是利用递归的方式进行储存的,链表中的每一个对象都是一个节点(Node),而每个节点对象中都存在一个数据对象(data)和存储下一个节点对象的节点对象(next),利用next节点对象实现链表之间的关联。
代码如下:
先创建一个节点对象类
package 单链表的实现;
public class Node{
public Object data;//用来存储对象数据
public Node next;//用来存储下一个节点对象
}
再创建一个list用来实现单链表
package 单链表的子我实现;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class list{
private Node head;
public list()
{
head=new Node();
}
public void traverse()
{
Node temp=head;
while(temp.next!=null)
{
temp=temp.next;
System.out.println(temp.data);
}
}
public boolean add(Object e) {
// TODO Auto-generated method stub
Node temp=head;//将头部对象赋值给临时对象,没有头部将无法遍历链表
//利用递归执行循环,当下一个节点对象为空时停止循环
/**
*注意!!
*data中存储的是当前对象,而next存储的是下一个对象
*temp=temp.next是将temp的下一个对象赋值给temp
*/
while(temp.next!=null)
{
//将对象的下一个对象赋值给现有的临时对象
//此时被赋值的temp节点对象同样拥有next对象
//依次类推就形成了单链表
temp=temp.next;
}
Node next=new Node();
next.data=e;
temp.next=next;
return true;
}
public Object get(int index) {
// TODO Auto-generated method stub
Node temp=head;
int i=0;
while(temp.next!=null)
{
if(i==index)
{
return temp.data;
}
i++;
}
return null;
}
public void add(int index, Object element) {
// TODO Auto-generated method stub
Node temp=head;
Node Element=new Node();
Element.data=element;
int i=0;
while(temp.next!=null)
{
if(i==index)
{
Node node=temp.next;
temp.next=Element;
Element=node;
}
i++;
}
}
}
再创建一个测试类
package 单链表的子我实现;
public class Test {
public static void main(String[] args)
{
list list=new list();
list.add("张三");
list.add("李四");
list.add("王武");
list.add("赵六");
list.traverse();
}
}
运行结果如下:
补充
其实在java中官方有一个类同样实现了单链表的结构,代码如下所示:
private static class Entry<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Entry<K,V> next;
protected Entry(int hash, K key, V value, Entry<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
@SuppressWarnings("unchecked")
protected Object clone() {
return new Entry<>(hash, key, value,
(next==null ? null : (Entry<K,V>) next.clone()));
}
// Map.Entry Ops
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
if (value == null)
throw new NullPointerException();
V oldValue = this.value;
this.value = value;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
(value==null ? e.getValue()==null : value.equals(e.getValue()));
}
public int hashCode() {
return hash ^ Objects.hashCode(value);
}
public String toString() {
return key.toString()+"="+value.toString();
}
}