在生活中容器是用来容纳东西的,在Java中也是,容器其实就是用来容纳和管理数据的。
在此之前的数组其实就是一种容器。
数组有简单,效率高,可以快速访问的优点,但是同时也有着不能扩容、不灵活的缺点。
因此数组不能满足我们的需要,所以我们需要一种更加强大的工具,也就是容器,也叫集合。
容器可以用下面的图来表示
首先先学习泛型
一、泛型
泛型的本质就是“数据类型的参数化”。 我们可以把“泛型”理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。
我们可以在类的声明处增加泛型列表,如:<T,E,V>。
此处,字符可以是任何标识符,一般采用这3个字母
泛型类的声明
class MyCollection<E> {// E:表示泛型;
Object[] objs = new Object[5];
public E get(int index) {// E:表示泛型;
return (E) objs[index];
}
public void set(E e, int index) {// E:表示泛型;
objs[index] = e;
}
}
泛型E像一个占位符一样表示“未知的某个数据类型”,我们在真正调用的时候传入这个“数据类型”。
public class TestGenerics {
public static void main(String[] args) {
// 这里的”String”就是实际传入的数据类型;
MyCollection<String> mc = new MyCollection<String>();
mc.set("aaa", 0);
mc.set("bbb", 1);
String str = mc.get(1); //加了泛型,直接返回String类型,不用强制转换;
System.out.println(str);
}
}
以上就是泛型的使用。在很多源代码中都有很多的泛型。
三、Collection接口的常见方法
Collection接口下面有两个子接口,list、set,所以在Collection中能够使用的方法在子接口下面也都能使用
一、List
list是一个接口,下面有ArrayList、LinkedList和Vector。三个实现类。
list其实偏数组多点,即有序行,索引方便。
下面是list里面常用的方法
1、ArrayList其实本质上就是数组,跟数组并没有什么区别,相关的增删、扩容等操作和数组的性质都相同。
2、LinkedList即为双向链表,它虽然查询效率较低但是增删效率很好,十分适合在要进行大量增删操作的时候使用。
它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。 所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。对应的图片如下:
即每个节点都有三个部分,前,数据,后,分别指向前前后后的数据。
代码表现应该如下:
class Node {
Node previous; //前一个节点
Object element; //本节点保存的数据
Node next; //后一个节点
}
下面会自己定义一个链表,一下是实现链表的add()增加元素的方法:
首先先定义一个Node节点类:
public class Node {
Node previous;
Object element;
Node next;
public Node(Node previous,Object element,Node next){
this.element=element;
this.next=next;
this.previous=previous;
}
public Node(Object element){
this.element=element;
}
}
在这个类里面有前后元素。
然后就是实现add方法的代码:
public class Linklist1 {
private Node last;
private Node first;
private int size;
public void add(Object obj){
Node node=new Node(obj);
if(first==null){
node.previous=null;
node.next=null;
first=node;
last=node;
}else{
node.previous=last;
node.next=null;
last.next=node;
last=node;
}
size++;
}
public String toString(){
Node temp=first;
while (temp!=null){
System.out.println(temp.element);
temp=temp.next;
}
return "";
}
public static void main(String[] args) {
Linklist1 list=new Linklist1();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);
}
}
其中重写了toString方法,以便能够打出来增加的元素。
下面是get()方法,即从链表中得到一个元素的方法
public class Linklist1 {
private Node last;
private Node first;
private int size;
public void add(Object obj){
Node node=new Node(obj);
if(first==null){
node.previous=null;
node.next=null;
first=node;
last=node;
}else{
node.previous=last;
node.next=null;
last.next=node;
last=node;
}
size++;
}
public Object get(int index){
Node temp=null;
Linklist1 linklist1=new Linklist1();
if(index<=(linklist1.size>>1)){
temp=first;
for(int i=0;i<index;i++){
temp=temp.next;
}
}else{
temp=last;
for(int j=size-1;j>index;j--){
temp=temp.previous;
}
}
return temp.element;
}
public String toString(){
Node temp=first;
while (temp!=null){
System.out.println(temp.element);
temp=temp.next;
}
return "";
}
public static void main(String[] args) {
Linklist1 list=new Linklist1();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
System.out.println(list.get(5));
}
}
这里是remove方法的实现:
public void remove(int index){
Node temp=getNode(index);
Node up=null;
Node down=null;
if(temp!=null){
up=temp.previous;
down=temp.next;
if(up!=null){
up.next=down;
}
if(down!=null){
down.previous=up;
}
}
if(index==0){
first=down;
}
if(index==size-1){
last=up;
}
}
下面是添加方法:
public void add(int index,Object obj){
Node newnode=new Node(obj);
Node temp=getNode(index);
Node up=null;
if(temp!=null){
up=temp.previous;
up.next=newnode;
newnode.previous=up;
temp.previous=newnode;
newnode.next=temp;
}
}
其实添加方法与删减都是一样的,在删减方法中引出要删减元素的up、down,让up与down相互联系,从而删除要删减元素,在增加方法中使用增加位置元素与它的up,让要增加元素与它的up和此元素相互联系,跟插队差不多。
3、vector
Vector底层是用数组实现的List,相关的方法都加了同步检查,因此“线程安全,效率低”。