Java 面向对象(十一)
常用类之集合
集合:就是用来存放数据的一个容器。
数组和集合的区别
(1)数组能存基本数据类型和引用类型;集合当中只能存放引用数据类型,直接放基本数据类型,也会自动帮你装箱(把基本数据类型转成对象),集合当中只能存放对象。
(2)数组长度是固定,不能再去增长;集合长度是可以改变,根据元素的增长而增加。
什么时候使用数组,什么时候使用集合类。
如果元素个数是固定,推荐使用数组;如果元素不是固定,推荐使用集合。
集合体系
这里介绍集合体系的一部分。
Collection 接口
常用方法
/*
* 向 collection 中添加指定的元素,
* 如果添加成功返回 true,没有添加返回 false。
* 确保此 collection 包含指定的元素。
*/
boolean add(E e)
/*
* 将指定 collection 中的所有元素都添加到此 collection 中
* 如果此 collection 由于调用而发生更改,则返回 true。 否则返回 false。
*/
boolean addAll(Collection<? extends E> c)
// 移除此 collection 中的所有元素
void clear()
// 如果此 collection 包含指定的元素,则返回 true。否则返回 false。
boolean contains(Object o)
// 如果此 collection 包含指定 collection 中的所有元素,则返回 true。否则返回 false。
boolean containsAll(Collection<?> c)
/*
* 比较此 collection 与指定对象是否相等。
* 如果所定义的两个列表以相同的顺序包含相同的元素,则返回 true。
*/
boolean equals(Object o)
// 如果此 collection 不包含元素,则返回 true。
boolean isEmpty()
// 返回在此 collection 的元素上进行迭代的迭代器。
Iterator<E> iterator()
// 从此 collection 中移除指定元素的单个实例,如果存在的话,移除成功,则返回 true。
boolean remove(Object o)
/*
* 移除此 collection 中,此 collection和指定 collection的交集
* 如果此 collection 由于调用而发生更改,则返回 true
*/
boolean removeAll(Collection<?> c)
/*
* 把此 collection和指定 collection的交集赋值给调用者
* 如果此 collection 由于调用而发生更改,则返回 true
*/
boolean retainAll(Collection<?> c)
// 返回此 collection 中的元素数。
int size()
// 返回包含此 collection 中所有元素的数组
Object[] toArray()
// 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
<T> T[] toArray(T[] a)
管理集合元素:
增:add(E e)
删:remove(Object o)
改:Collection中没有定义
清空:clear()
查:
个数:size()
判包含:contains(Object o)
判空:isEmpty()
查找定位某个元素:Collection中没有定义
e.g.
public static void main(String[] args) {
Collection c = new ArrayList();
// 会自动帮你装箱(把基本数据类型转成对象)
c.add(10);
c.add(true);
}
反编译后:
public static void main(String args[])
{
Collection c = new ArrayList();
c.add(Integer.valueOf(10));
c.add(Boolean.valueOf(true));
}
e.g. Collection 遍历
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(new Student("zs"));
c.add(new Student("ls"));
c.add(new Student("ww"));
// (1)转成数组,通过数组遍历
Object[] array = c.toArray(); // 自动把数组当中所有元素向上转型
for (int i = 0; i < array.length; i++) {
if (array[i] instanceof Student) { // 向下转型有风险
Student s = (Student) array[i]; // 向下转型(转回原来存放的类型)
System.out.println(s.name);
}
}
System.out.println("-----分割线------");
// (2)迭代器遍历(推荐)
Iterator it = c.iterator(); // 放到Iterator内容会自动类型提升为 Object
// 1.判断有没有元素可以迭代,如果仍有,则返回 true。
while (it.hasNext()) {
// 2. 返回游标的下一个元素,游标后移一位
Object next = it.next();
if (next instanceof Student) {
Student s = (Student) next;
System.out.println(s.name);
}
}
}
List 接口
常用方法
由 Collection 接口继承来的不再说明,见Collection 接口的常用方法
// 在列表的指定位置插入指定元素
void add(int index, E element)
/*
* 将指定 collection 中的所有元素都插入到列表中的指定位置
* 如果此 collection 由于调用而发生更改,则返回 true。 否则返回 false。
*/
boolean addAll(int index, Collection<? extends E> c)
// 移除列表中指定位置的元素,返回从列表中移除的元素
E remove(int index)
// 返回列表中指定位置的元素
E get(int index)
// 用指定元素替换列表中指定位置的元素,返回被替换的元素
E set(int index, E element)
// 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
int indexOf(Object o)
// 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1
int lastIndexOf(Object o)
// 返回此列表元素的列表迭代器(按适当顺序)
ListIterator<E> listIterator()
// 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始
ListIterator<E> listIterator(int index)
// 返回列表中指定的 [fromIndex, toIndex) 之间的部分视图。
List<E> subList(int fromIndex, int toIndex)
// 使用随附的 Comparator排序此列表来比较元素。
default void sort(Comparator<? super E> c)
管理集合元素:
增:add(E e) ; add(int index, E element)
删:remove(Object o) ; remove(int index)
改:set(int index, E element)
清空:clear()
排序:sort(Comparator<? super E> c)
子集合:subList(int fromIndex, int toIndex)
查:
个数:size()
判包含:contains(Object o)
判空:isEmpty()
查找定位某个元素:indexOf(Object o) ; lastIndexOf(Object o) ; get(int index)
e.g.
现在有个需求,遍历集合,如果集合中的元素等于某个值,删除这个元素。
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// 遍历集合
Iterator it = list.iterator();
while(it.hasNext()) {
// 取出对应的元素
String str = (String)it.next();
// 判断该 元素是否等于 2
if(str.equals("2")) {
// 等于 2 就把2给集合当中删除
list.remove("2");
}
}
System.out.println(list);
以上代码会报 java.util.ConcurrentModificationException 并发修改异常
在迭代集合的过程当中,是不允许直接修改集合结构。
看下源码:
修改后:
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
Iterator it = list.iterator();
while(it.hasNext()) {
String str = (String)it.next();
if(str.equals("2")) {
it.remove(); // 删除当前正在迭代集合的元素(正在遍历的元素 next的结果)
}
}
System.out.println(list);
原理:
e.g. List特有的迭代器
现在换了一个需求,遍历集合,如果集合中的元素等于某个值,在这个元素后添加一个元素。
在迭代器中,只有remove方法,没有add方法。但是在List中有自己特有的迭代器 listIterator
private class ListItr extends Itr implements ListIterator<E>
ListItr 继承了 Itr,所以 Itr 有的方法都能用。
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// 在list当中有自己特有的迭代器
ListIterator it = list.listIterator();
while (it.hasNext()) {
String str = (String) it.next();
if (str.equals("2")) {
// list.add("myxq"); //会发生并发修改异常
it.add("myxq");
}
}
System.out.println(list);
ArrayList
数据结构分析
数组的大小是固定的,ArrayList 数组扩容的实现:
查询和修改比较快,通过索引就能找到对应值。
添加和删除比较慢
这也就实现了当我们不指定初始化大小的时候,添加第一个元素的时候,数组会扩容为 10.
添加和删除图示:
ArrayList 去除集合中重复的元素
public static ArrayList removeDuplicates(ArrayList list) {
// 1.创建一个空的集合
ArrayList newList = new ArrayList();
// 2.依次取出每一个元素
ListIterator it = list.listIterator();
while (it.hasNext()) {
// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
Object obj = it.next();
// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
if (!newList.contains(obj)) {
newList.add(obj);
}
}
return newList;
}
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
list.add("d");
System.out.println(list);
ArrayList newList = removeDuplicates(list);
System.out.println(newList);
}
ArrayList 去除集合中重复的自定义对象元素
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Test {
public static ArrayList removeDuplicates(ArrayList list) {
// 1.创建一个空的集合
ArrayList newList = new ArrayList();
// 2.依次取出每一个元素
ListIterator it = list.listIterator();
while (it.hasNext()) {
// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
Object obj = it.next();
// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
if (!newList.contains(obj)) {
newList.add(obj);
}
}
return newList;
}
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("张三", 20));
list.add(new Student("张三", 20));
list.add(new Student("李四", 21));
System.out.println(list);
ArrayList newList = removeDuplicates(list);
System.out.println(newList);
}
}
以上代码发现并没有去重。
原因是 contains 是用equals(如果没有重写,默认是Object的equals,比较的是地址)判断有没有相同的元素。
修改后
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Test {
public static ArrayList removeDuplicates(ArrayList list) {
// 1.创建一个空的集合
ArrayList newList = new ArrayList();
// 2.依次取出每一个元素
ListIterator it = list.listIterator();
while (it.hasNext()) {
// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
Object obj = it.next();
// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
if (!newList.contains(obj)) {
newList.add(obj);
}
}
return newList;
}
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("张三", 20));
list.add(new Student("张三", 20));
list.add(new Student("李四", 21));
System.out.println(list);
ArrayList newList = removeDuplicates(list);
System.out.println(newList);
}
}
LinkedList
数据结构分析
添加和删除比较快,查询和修改比较慢。
LinkedList 特有的方法
// 将指定元素插入此列表的开头。
void addFirst(E e)
// 将指定元素添加到此列表的结尾。
void addLast(E e)
// 获取但不移除此列表的头(第一个元素)。
E element()
// 返回此列表的第一个元素。
E getFirst()
// 返回此列表的最后一个元素。
E getLast()
// 获取并移除此列表的头(第一个元素)。
E remove()
// 移除并返回此列表的第一个元素。
E removeFirst()
// 移除并返回此列表的最后一个元素。
E removeLast()
// 将指定元素添加到此列表的末尾(最后一个元素)。
boolean offer(E e) // 类似 add(E e)
// 在此列表的开头插入指定的元素。
boolean offerFirst(E e) // 类似 addFirst(E e)
// 在此列表末尾插入指定的元素。
boolean offerLast(E e) // 类似 addLast(E e)
// 获取但不移除此列表的头(第一个元素)。
E peek() // 类似 element()
// 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekFirst() // 类似 getFirst()
// 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
E peekLast() // 类似 getLast()
// 获取并移除此列表的头(第一个元素)
E poll() // 类似 remove()
// 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollFirst() // 类似 removeFirst()
// 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pollLast() // 类似 removeLast()
// 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
boolean removeFirstOccurrence(Object o)
// 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。
boolean removeLastOccurrence(Object o)
// 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。元素将按从最后一个(尾部)到第一个(头部)的顺序返回。
Iterator<E> descendingIterator()
栈:先进后出
// 出栈:从此列表所表示的堆栈处弹出一个元素。
E pop() // 底层调用 removeFirst(e);
// 入栈:将元素推入此列表所表示的堆栈。
void push(E e) // 底层调用 addFirst(e);
Vector
Vector使用很少,一般都使用ArrayList 从1.2开始并到List
特有的方法
// 将指定的组件添加到此向量的末尾,将其大小增加 1。
void addElement(E obj)
// 返回此向量的组件的枚举。
Enumeration<E> elements()
e.g. 特有的遍历元素
Vector vc = new Vector();
vc.add("a");
vc.add("b");
vc.add("c");
// 获取所有元素
Enumeration e = vc.elements();
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
与ArrayList对比
(1)都是使用数组来实现的
(2)Vector是线程安全的,内部加了锁;ArrayList当中方法没有加锁
集合的嵌套
class Student {
String name;
Student(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
/**
* 学科 学科当中是有很多班级
* 班级当中又有很多学生
*/
Student stu1 = new Student("zs1");
Student stu2 = new Student("ls1");
// 班级1
List<Student> c1 = new ArrayList<>();
c1.add(stu1);
c1.add(stu2);
Student stu3 = new Student("zs2");
Student stu4 = new Student("ls2");
// 班级2
List<Student> c2 = new ArrayList<>();
c2.add(stu3);
c2.add(stu4);
// 学科 (集合当中又存储集合)
List<List<Student>> x = new ArrayList<>();
x.add(c1);
x.add(c2);
// 把所有班级当中 的学生姓名打印出来
for (List<Student> g : x) {
// 取出每一个班级
for (Student per : g) {
System.out.println(per.name);
}
}
}
}
Java 面向对象(十一)的更多相关文章
- 1903021121-刘明伟-java十一周作业-java面向对象编程
项目 内容 课程班级博客链接 19级信计班(本) 作业要求链接 第十一周作业 博客名称 1903021121-刘明伟-java十一周作业-java面向对象 要求 每道题要有题目,代码(使用插入代码,不 ...
- Java学习笔记二十一:Java面向对象的三大特性之继承
Java面向对象的三大特性之继承 一:继承的概念: 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方 ...
- 20155303 实验二 Java面向对象程序设计
20155303 实验二 Java面向对象程序设计 目录 一.单元测试和TDD 任务一:实现百分制成绩转成"优.良.中.及格.不及格"五级制成绩的功能 任务二:以TDD的方式研究学 ...
- JAVA面向对象
JAVA面向对象 对象 我们生活中能看到能摸到的一切事物都是对象.在程序中模拟出生活中的所有东西万物皆对象 只要是对象--属性和行为(方法) 属性 对象有什么 例如:学生有姓名.学 ...
- 理解JAVA - 面向对象(object) - 属性,方法
理解JAVA - 面向对象(object) - 属性,方法 多态的体现: 向上造型,父类接收子类对象:向上造型: 从父类角度看不到子类独有的方法:面向对象,人类认知世界的方式:生活中每天都 ...
- Java面向对象㈠ -- 封装
Java的面向对象有三大特征:封装.继承.多态.这里主要对封装进行讲解. 封装可以理解为隐藏一个类的成员变量和成员函数,只对外提供需要提供的成员函数. Java的封装主要通过访问权限控制符:priva ...
- 谈谈Java面向对象的三大特性
Java面向对象的三大特性就是指封装.继承.多态了. 一.封装: 概念:封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. (举例:笔记本电脑就是一个封装体,Java语言中最小的封装体就是函数 ...
- Java面向对象:接口
Java面向对象之接口 什么是接口:接口是一种规范和标准,他们可以约束类的行为,是一些方法特征的集合 语法: [修饰符] interface 接口名 extends 父接口1,夫接口2....... ...
- 实验二 Java面向对象程序设计
实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...
- java基础1.0::Java面向对象、面向对象封装、抽象类、接口、static、final
一.前言 一直以来都是拿来主义,向大神学习,从网上找资料,现在就把自己在工作中和学习中的所理解的知识点写出来,好记星不如烂笔头,一来可以作为笔记自己温习,二来也可以给走在求学之路的同学们一点参考意见, ...
随机推荐
- Java虚拟机(五):JVM 类加载机制
一.JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 1. 加载: 加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表 ...
- 本文可能是国内第一篇介绍C/4HANA Foundation的中文博客
SAP C/4HANA从去年发布已经过去了一年多的时间,C/4HANA的从业者,对于这五朵云里包含的产品集,想必都有了一些了解. Jerry注意到,SAP C/4HANA Foundation这个概念 ...
- [LeetCode] 300. 最长上升子序列 ☆☆☆(动态规划 二分)
https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-she-ji-fan ...
- CentOS7.x安装nginx
1.安装先决条件 yum install yum-utils 2.设置yum存储库和创建/etc/yum.repos.d/nginx.repo 使用以下内容命名的文件 :稳定版 [nginx-stab ...
- scikit-learn中的机器学习算法封装——kNN
接前面 https://www.cnblogs.com/Liuyt-61/p/11738399.html 回过头来看这张图,什么是机器学习?就是将训练数据集喂给机器学习算法,在上面kNN算法中就是将特 ...
- Mybatis.NET Oracle 线上神奇问题:Value does not fall within the expected range.
1.错误现象 在向数据库查询一条数据的时候报如下错误: Value does not fall within the expected range. at Oracle.ManagedDataAcce ...
- python 多分类任务中按照类别分层采样
在机器学习多分类任务中有时候需要针对类别进行分层采样,比如说类别不均衡的数据,这时候随机采样会造成训练集.验证集.测试集中不同类别的数据比例不一样,这是会在一定程度上影响分类器的性能的,这时候就需要进 ...
- 【数组模拟的链表or复杂模拟】PAT-L2-002. 链表去重
L2-002. 链表去重 给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点.即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留.同时,所有被删除的结点必须 ...
- Docker那些事儿之编排工具docker-compose
前面已经讲解过docker的一些基础使用,镜像创建的操作过程,如果大量容器需要同时部署,一个一个容器进行服务器上的部署,估计要疯掉,在使用上我们需要找到更好更便捷的使用方式,今天要讲解的容器编排工具d ...
- 我们什么时候应该在C程序中使用指针?
回答: 传递大型结构喜欢服务器请求或响应数据包. 实现链表和二叉树. 使用GPIO或硬件寄存器. 从函数中获取地址或更新值(通过引用调用) 创建动态数组. 使用函数指针创建回调函数. 注意:除此之外, ...