Collection集合(上) -- list
集合(Collection<E>):是一个容器,可以存储多个数据且长度不确定
<E> ------- 泛型 : 用于指定集合元素的数据(对象)类型,由泛型指定的元素类型都要是引用类型
int[ ] a; a ----------数组类型,a中的元素类型式整型
Collection<String> c ; c 是集合类型(引用类型),元素类型是String
Collection<Integer> c;存储 1.2.3 整型值(基本类型数据也可以进行存储-–-–--—转成对应的包装类)
Collection<E> 是集合的顶级接口
子接口:List,Set,Queue,Deque 。。。。
list(序列,列表): 有序
存入数据有序,可以通过下标进行操作
import java.util.ArrayList; import java.util.List; public class ListDemo{ public static void main(String[] args) { //c创建了一个集合对象 List<String> list = new ArrayList<>(); //添加对象 list.add("a"); list.add("f"); list.add("c"); list.add("b"); //插入元素 list.add(0, "1"); //末尾添加 list.add(5, "2"); System.out.println(list); //[1, a, f, c, b, 2] //根据下标进行删除 list.remove(0); //删除具体元素 //如果要删除的元素不在集合中,就不执行 list.remove("9"); System.out.println(list); //[a, f, c, b, 2] //判断字符串是否在几何中 System.out.println(list.contains("2")); //true //获取元素,根据下标值,返回集合对应的元素值 System.out.println(list.get(1)); //f //根据元素值,返回对应集合的下标值,如果没有返回-1 System.out.println(list.indexOf("c")); //2 //判断集合中是否含有元素 System.out.println(list.isEmpty()); //false //替换 System.out.println(); //清空集合 list.clear(); System.out.println(list); //[] } }
import java.util.ArrayList; import java.util.List; public class ListDemo{ public static void main(String[] args) { //c创建了一个集合对象 List<String> list = new ArrayList<>(); //添加对象 list.add("a"); list.add("f"); list.add("c"); list.add("b"); // list.remove(1); // list.add(1, "2"); // System.out.println(list); //根据下标修改元素 list.set(1, "2"); System.out.println(list); //返回集合中元素的个数 System.out.println(list.size()); //4 //返回一个子列表,左闭右开 System.out.println(list.subList(1, 3)); //[2, c] } }
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ListDemo{ public static void main(String[] args) { //c创建了一个集合对象 List<String> list = new ArrayList<>(); //添加对象 list.add("a"); list.add("f"); list.add("c"); list.add("b"); //再转数组过程中,指定要转成的类型 String[] ss=list.toArray(new String[0]); System.out.println(Arrays.toString(ss)); //[a, f, c, b] } }
list实现类:ArrayList,LinkList, Vector,Stack
ArrayList(顺序表):
基于数组实现,默认数组的初始容量为10,默认扩容是基于右移运算,在原来的基础上加上一半 10 10+5 15+7 ......
查询效率较高,增删元素效率较低,是一个线程不安全的集合
练习:通过数组实现ArrayList
import java.util.Arrays; /* * 通过数组实现ArrayList * * */ public class ListDemo { public static void main(String[] args) { ListArray list = new ListArray(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add(0,"1"); list.add(5,"2"); list.remove(0); list.remove("2"); System.out.println(list); } } class ListArray { // 存储数据的数组 String[] date; // 表示元素个数 int size = 0; // 无参构造 public ListArray() { // 默认长度为10 date = new String[10]; } // 有参构造------指定数组长度 public ListArray(int initCapcity) { date = new String[initCapcity]; } //数组扩容 public void grow(){ //处理特殊的情况,数组长度为0和1的情况 if(date.length<=1){ date = Arrays.copyOf(date, date.length+1); }else { //在原来的基础上加一半 date = Arrays.copyOf(date, date.length+(date.length>>1)); } } //下标越界 public void out(int index){ //判断下标是否越界 if(size >=date.length){ grow(); } } // 添加元素 public void add(String str) { //判断是否需要扩容 if(size>=date.length){ grow(); } //添加元素,数组下标往后挪动,集合元素+1 date[size++]=str; } //插入 public void add(int index,String str){ //判断下标是否越界 if(index<0||index>size){ throw new IllegalArgumentException("index:"+index); } //判断是否需要扩容 if(size>=date.length){ grow(); } //开始插入 //法一 //依次遍历后面需要移动的元素 // for(int i=size-1;i>=index;i--){ // //依次进行前面的值赋值给后面的值 // date[i+1] = date[i]; // } // //法二 System.arraycopy(date, index, date, index+1,size-index ); //插入值 date[index]=str; //元素加1 size++; } //删除 public void remove(int index ){ //下标越界 out(index); //可以进行删除 //依次遍历需要移动的元素 for(int i=index;i<size-1;i++){ //后面的值赋值给前面的值 date[i]= date[i+1]; } // System.arraycopy(date,index+1,date,index,size-(index+1)); //元素减1 size--; } //删除----根据元素 public void remove(String str){ //返回参数对应的下标值 int index = indexOf(str); //判断下标值是否等于-1 if(index!=-1){ remove(index); } } //返回第一次出现的下标值 public int indexOf(String str){ for(int i =0;i < size;i++){ //判断参数与数值是否相等 if(str==date[i]||str!=null&&str.equals(date[i])){ return i; } } return -1; } //清空列表 public void clear(){ //让元素个数为0 size=0; } //是否包含 public boolean contains(String str){ //表示在列表中是否出现 return indexOf(str)!=-1; } //获取元素 public String get(int index){ //判断参数是否越界 out(index); //返回下标值 return date[index]; } //判断列表是否为空 public boolean isEmpty(){ return size==0; } //替换元素 public void set(int index,String str){ //判读那参数是否越界 out(index); //替换 date[index]=str; } //返回元素个数 public int size(){ return size; } //截取子列表 public ListArray subList(int fromindex,int toindex){ //判断参数是否都越界 out(fromindex); out(toindex); //判断起始下标是否小于结束下标 if(fromindex>toindex){ throw new IllegalArgumentException("FromIndex:"+fromindex); } //截取的元素个数 int count = toindex - fromindex; //创建新列表 ListArray list = new ListArray(); //数组之间的复制(原数组和新数组的复制) System.arraycopy(date, fromindex, list.date, 0, count); //改变新列表的元素个数 list.size=count; //返回子列表 return list; } //重写toString方法 @Override public String toString(){ //创建对象进行拼接 StringBuilder sb = new StringBuilder("["); //遍历数组元素进行拼接 for(int i= 0; i<size;i++){ sb.append(date[i]).append(", "); } //转成字符串 String str = sb.toString(); //截取子串 if(size>0){ str = str.substring(0,str.length()-2); } return str+="]"; } }
LinkedList(链表)
底层基于节点进行实现的,底层内存不连续,增删元素效率较高,查询元素效率较低,是一个线程不安全的集合。
练习,实现LinkedList
思考:在某个场景下,列表的增删与查询出现的机率几乎一致,用ArrayList还是LinkedList?
LinkedList:时间消耗差不多,ArrayList会进行扩容操作,会降低内存利用率,而LinkedList不会出现大量的空间占用
import java.util.LinkedList; /* * 实现LinkedList */ public class ListDemo { public static void main(String[] args) { LinkedList<String> str = new LinkedList<String>(); str.addAll(str); } } class ListLinked{ //节点个数 int size=0; //头节点 Node first; //尾节点 Node last; //内部类---节点 class Node{ //存储的元素 String item; //上一个节点 Node prev; //下一个节点 Node next; //有参构造 public Node(String item,Node prev,Node next){ this.item=item; this.next=next; this.prev = prev; } } public void add(String str){ //创建一个新节点 Node node = new Node(str, null, null); //判断在什么位置进行添加节点 if(size==0){ //表明链表无节点,添加第一个节点 //头节点要指向新节点 this.first = node; }else{ //添加最后一个节点 //原最后一个节点的下一个节点指向新节点 this.last.next = node; //新节点的上一个节点指向左后一个节点 node.prev=this.last; } //尾节点指向新节点 this.last=node; } //插入 public void add(int index,String str){ //判断下标是否越界 if(index<0||index>size){ throw new IllegalArgumentException("Index:"+index); } //创建新节点 Node node = new Node(str,null,null); //判断插入的位置 if(index==0){ //插到第一个节点 //判断插入第一个节点之前,链表是否还有其他节点 if(size==0){ add(str); //保证添加一个节点,size就加一次 return; } //有其他节点的插入情况 //原第一个节点的上一个节点指向新节点 this.first.prev = node; //新节点的下一个节点指向原第一个节点 node.next= this.first; //头节点指向新节点 this.first=node; }else if(index==size){ //添加最后一个节点 // add(str); //保证添加一个节点 return; }else{ //在中间位置进行添加 //通过下标找到对应的节点 Node no = this.first; for(int i = 0;i<index;i++){ no=no.next; } //no节点的上一个节点的下一个节点,指向新节点 no.prev.next = node; //新节点的上一个节点指向no的下一个节点 no.prev=no.prev; //no节点的上一个节点指向新节点 no.prev=node; //新节点的下一个节点指向no节点 // no.next=node; } } }
保存redis相关笔记

浙公网安备 33010602011771号