[19/03/24-星期日] 容器_Collection(集合、容器)之List(表,有顺序可重复)
一、 概念&方法
Collection 表示一组对象,它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。
由于List、Set是Collection的子接口,意味着所有List、Set的实现类都有上面的方法。
如参见代码中test01和test02方法
【list接口】分为3种
List是有序、可重复的容器。List接口常用的实现类有3个:ArrayList(数组实现)、LinkedList(链表)和Vector(线程)。
有序:List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。
可重复:List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。
除了Collection接口中的方法,List多了一些跟顺序(索引)有关的方法,参见下表(测试代码test03):
1 /*
2 *测试list(接口) 需要用类去实现 如实现类ArrayList
3 * Collection接口的两个子接口是List、Set接口
4 */
5 package cn.sxt.collection;
6
7 import java.util.*;
8
9 public class Test_0324_List {
10 public static void main(String[] args) {
11 test03();
12
13
14 }
15 //测试Collection中单个容器的基本操作
16 public static void test01() {
17 Collection<String> c =new ArrayList<>();
18 System.out.println(c.size());//容器中元素的数量
19 System.out.println(c.isEmpty());//容器是否为空
20 c.add("Jack");//容器中增加元素
21 c.add("Tom");
22 System.out.println(c);//输出容器中的元素
23 System.out.println(c.contains("Tom"));//是不是包含Tom 是的话返回true
24
25 Object[] objs = c.toArray(); //把容器转成Object数组
26 System.out.println(Arrays.toString(objs));
27
28 c.remove("Jack");//把"Jack"的引用地址从对象c的容器中移除,并不是在内存中删除"Jack"
29 System.out.println(c);
30 c.clear();//清空所有元素
31 System.out.println(c.size());
32 }
33 //测试Collection中2个容器的操作
34 public static void test02() {
35 List<String> list01=new ArrayList<String>();//List可替换成Collection(因为前者是后者的子接口)
36 list01.add("a");
37 list01.add("b");
38 list01.add("c");
39
40 List<String> list02=new ArrayList<String>();
41 list02.add("a");
42 list02.add("e");
43 list02.add("f");
44
45 System.out.println("list01:"+list01);
46 System.out.println("list02:"+list02);
47
48 list01.addAll(list02);//最终元素落脚点在01容器中 取并集
49 System.out.println("把02的元素全部添加在01中(包括重复的):"+list01);
50 list01.removeAll(list02);//把01中 01和02都有的元素删掉(即a元素)
51 System.out.println("把01和02都有的元素删掉(即a元素):"+list01); //removeAll 移除共有的
52 list01.retainAll(list02);//取交集
53 System.out.println("把01和02都有的元素保留(其它删除):"+list01);//retainAll 保留共有的
54 System.out.println("01是否包含02中的所有元素:"+list01.contains(list02));//contains:包含的
55
56 }
57 //测试list接口中独有的方法 与索引相关
58 public static void test03() {
59 List<String> list=new ArrayList<String>();
60 list.add("A");
61 list.add("B");
62 list.add("C");
63 list.add("D");
64 System.out.println(list);
65
66 list.add(2, "小白");//在下标为2的位置插入一个新的元素,其它往后边移动
67 System.out.println(list);
68
69 list.remove(2);//把下标为2的位置的元素删除
70 System.out.println(list);
71
72 list.set(2, "菜鸟");//把下标为2的位置的元素替换掉
73 System.out.println(list);
74
75 System.out.println(list.get(2));//返回下标为2的处的元素
76
77 list.add("B");
78 System.out.println(list);
79
80 System.out.println(list.indexOf("B"));//返回元素"B"第一次出现时的下标
81 System.out.println(list.indexOf("F"));//返回元素"F"第一次出现时的下标,没有这个元素返回-1
82 System.out.println(list.lastIndexOf("B"));//返回元素"B"最后一次出现时的下标
83
84
85
86 }
89
90 }
ArrayList(数组):
1、底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。ArrayList底层使用Object数组来存储元素数据。
所有的方法,都围绕这个核心的Object数组来开展。
2、 数组长度是有限的,而ArrayList是可以存放任意数量的对象,长度不受限制,那么它是怎么实现的呢?
本质上就是通过定义新的更大的数组,将旧数组中的内容拷贝到新数组,来实现扩容。ArrayList的Object数组初始化长度为10,
如果我们存储满了这个数组,需要存储第11个对象,就会定义新的长度更大的数组,并将原数组内容和新的元素一起加入到新数组中。
LinkedList(链表):
1、底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。
所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。
class Node {
Node previous; //前一个节点
Object element; //本节点保存的数据
Node next; //后一个节点
}
【代码示例】
/*
*测试链表 增删改查
*
*/
package cn.sxt.collection; public class Test_0324_LinkList<E> { //加了泛型的主类
private Node firstNode; //同一个包下的Node类 链表的第一个节点
private Node lastNode; // 链表的最后一个节点
private int size=0; public static void main(String[] args) { //主方法
Test_0324_LinkList<String> list=new Test_0324_LinkList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
System.out.println(list);//toString的好处是在碰到“println”之类的输出方法时会自动调用,不用写出来。
//System.out.println(list.get(1));//调用下边的get方法 给个索引位置返回具体元素
//list.remove(0);
list.insert(2, "我");
System.out.println(list);
} //添加一个新节点的方法
public void add(E e) {
Node node=new Node(e);//node 为新建的节点
if (firstNode==null) {//如果链表为空,新进来一个元素,则第一元素和最后一个元素都是它,因为链表中就一个元素
firstNode=node;
lastNode=node; } else { //如果不为空,新进来一个元素,新元素的前置节点就是原来的最后一个节点,同时把新元素的后置指针置为空
node.previous=lastNode;
node.next=null;
lastNode.next=node;//原来最后一个节点的后置节点就变成一个新节点了
lastNode=node; //新的节点就变成最后一个节点了
//每多加个字符,size加1 代表链表长度
}
size++;
} private void checkRange(int index) { //索引封装
if (index<0||index>size-1) {//判断索引位置是否合法
throw new RuntimeException("索引数字不合法:"+index);//抛出异常
} } //给个索引位置,返回具体元素的某项指标, 这里是这个元素的数值
public E get(int index) {
System.out.println(size); //做测试用 测试size的大小 checkRange(index);
Node temp=getNode(index);
return (temp!=null)? (E)temp.element:null;// (E)强制转型 如果temp不为空返回冒号前边的temp.element 否则返回null
} //通过索引返回一个具体元素
public Node getNode(int index){
checkRange(index);
Node tempNode=null;
//优化,当链表中数据比较多时用着快速
if (index<=(size>>1)) { //size>>1 右移1位相当于除以2
tempNode=firstNode;
for (int i=0; i<index; i++) {//通过for循环把索引所在的位置节点找出来,然后输出元素值
tempNode=tempNode.next; //如果小于中间值从前往后搜
}
}else {
tempNode=lastNode;
for (int i=index-1;i>index; i--) {//大于中间值,从后往前搜
tempNode=tempNode.previous;
}
}
return tempNode;
}
//在链表中插入一个元素
public void insert(int index,E e){ //alt+shift+R 替换字母
checkRange(index);
Node newNode=new Node(e);
Node tempNode=getNode(index);
if (tempNode!=null) {
Node up=tempNode.previous; up.next=newNode;
newNode.previous=up; newNode.next=tempNode;
tempNode.previous=newNode; }
/*if (index==0){ //在第一个位置增加元素的情况。 待完善!
firstNode=newNode.next;
lastNode=newNode.previous; lastNode.next=newNode;
newNode.previous=lastNode;
}
*/
size++; } //在链表中删除一个元素
public void remove(int index) {
checkRange(index);
Node tempNode=getNode(index);
if (tempNode!=null) {
Node up=tempNode.previous;
Node down=tempNode.next;
if (up!=null) {
up.next=down; //把这个元素后一个元素的地址直接放在这个元素前一个元素的next指针域
}
if (down!=null){
down.previous=up;// 把这个元素前一个元素的地址直接放在这个元素后一个元素的previous指针域
}
if (index==0){ //删除第1个元素的情况。 下一个元素是第一个元素
firstNode=down;
}
if (index==size-1){//删除最后1个元素的情况
lastNode=up;
}
}
size--; } //输出链表中的元素 toString的好处是在碰到“println”之类的输出方法时会自动调用,不用写出来。
public String toString () {
StringBuilder sb=new StringBuilder("[");//字符串 对象sb初始化 初始为字符串"[",然后依次追加 Node tempNode=firstNode; //初始临时节点为链表的第一个节点
while (tempNode!=null) {//如果元素不为空则输出元素的数据
sb.append(tempNode.element+","); //append 追加单个字符
tempNode=tempNode.next; //通过next找到下一个元素
}
sb.setCharAt(sb.length()-1,']'); //把sb对象的最后单个一个字符设置为"]"
return sb.toString();
} }
Vecto(矢量、向量)
Vector底层是用数组实现的List,相关的方法都加了同步检查,因此“线程安全,效率低”。 比如,indexOf方法就增加了synchronized同步标记。
区别:
如何选用ArrayList、LinkedList、Vector?
1. 需要线程安全时,用Vector。
2. 不存在线程安全问题时,并且查找较多用ArrayList(一般使用它)。
3. 不存在线程安全问题时,增加或删除元素较多用LinkedList。
[19/03/24-星期日] 容器_Collection(集合、容器)之List(表,有顺序可重复)的更多相关文章
- [19/03/25-星期一] 容器_Collection(集合、容器)之Set(集合、安置,无顺序不可重复)
一.概念&方法 Set接口继承自Collection,Set接口中没有新增方法,方法和Collection保持完全一致.. Set容器特点:无序.不可重复.无序指Set中的元素没有索引,只能遍 ...
- 编程体系结构(03):Java集合容器
本文源码:GitHub·点这里 || GitEE·点这里 一.集合容器简介 集合容器是Java开发中最基础API模块,通常用来存储运行时动态创建的元素,基本特点如下: 泛型特点,存储任意类型对象: 动 ...
- C++STL之set集合容器
set集合容器 set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构, 在 插入元素时, 它会自动调整二叉树的排列, 把该元素放到适当的位置, 以确保每个子树根节点的键 ...
- [19/03/27-星期三] 容器_Iterator(迭代器)之遍历容器元素(List/Set/Map)&Collections工具类
一.概念 迭代器为我们提供了统一的遍历容器的方式 /* *迭代器遍历 * */ package cn.sxt.collection; import java.security.KeyStore.Ent ...
- [19/03/23-星期六] 容器_ 泛型Generics
一.概念 生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据. 数组就是一种容器,可以在其中放置对象或基本类型数据. ---优势:是一种简单的线性序列,可以 ...
- stl之set集合容器应用基础
set集合容器使用一种称为红黑树(Red-Black Tree) 的平衡二叉检索树的数据结构,来组织泛化的元素数据.每一个节点包括一个取值红色或黑色的颜色域.以利于进行树的平衡处理.作为节点键值的元素 ...
- 【STL】 set集合容器常用用法
set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还 ...
- Java集合容器简介
Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...
- Java 容器(集合)
import java.util.*; 一.基础概念 1.什么是容器? 2.为什么需要容器? 3.容器的分类? 二.重点知识 List接口 Collections类 (1)为什么需要? Collect ...
随机推荐
- C语言中的输入方式
在c语言中,有gets().scanf().getchar()等输入方式,但是不同的方式处理的方式不同. scanf()读取时遇见tab.space.enter时会结束读取,不会舍弃最后的回车符(即回 ...
- gulp优化hexo方法
gulp通过对站点使用的静态资源进行压缩,来优化网站的访问速度. 首先安装gulp以及所需要的模块: npm install gulp -g npm install gulp-htmlclean gu ...
- fiter 编码
package com.itheima.web.filter; import java.io.IOException; import javax.servlet.Filter; import java ...
- 017-Servlet抽取时的BaseServlet模板代码
package www.test.web.servlet; import java.io.IOException; import java.lang.reflect.Method; import ja ...
- Unity游戏项目常见性能问题
Unity技术支持团队经常会对有需求的客户公司项目进行游戏项目性能审查与优化,在我们碰到过的各种项目相关的问题中也有很多比较共同的方面,这里我们罗列了一些常见的问题并进行了归类,开发者朋友们可以参考下 ...
- bzoj 5298: [Cqoi2018]交错序列
Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻的0).例如,000,001 ,101,都是交错序列,而110则不是.对 ...
- 3、card 卡片
1.基本用法的使用 /* --- htm l----*/ <ion-content> <ion-card> <ion-card-header> Header < ...
- git每次提交都输入密码
打开gitbash执行即可 git config --global credential.helper store 长期储存密码,因为git默认是不储存密码的,不执行这条命令的话每次更新代码,或者提交 ...
- C# ADO.NET
ADO.NET 作业总结难点 数据库语句掌握太差 //查询 select * from Users //查询表中所有数据 select * from Users where UserName = 'l ...
- python学习(五)--打印错误信息
from urllib import request #打印错误信息 except Exceptionlist = [ "http://www.baidu11.com/", &qu ...