系列文章目录
Java核心技术卷一 -第一章:java“白皮书”的关键术语
Java核心技术卷一 -第三章:数据类型
Java核心技术卷一 -第三章:变量与常量
Java核心技术卷一 -第三章:运算符
Java核心技术卷一 -第三章:字符串
Java核心技术卷一 -第三章:输入与输出
Java核心技术卷一 -第三章:数组
Java核心技术卷一 -第四章:类之间的关系-依赖
Java核心技术卷一 -第四章:预定义类-LocalDate类小应用
Java核心技术卷一 -第四章:构造器
Java核心技术卷一 -第四章:null引用
Java核心技术卷一 -第四章:方法参数
Java核心技术卷一 -第四章:对象构造
Java核心技术卷一 -第五章:覆盖方法与super
Java核心技术卷一 -第五章:super关键字
Java核心技术卷一 -第五章:类的强制类型转换与instanceof操作符
Java核心技术卷一 -第五章:抽象类与abstract关键字
Java核心技术卷一 -第五章:Object类的toString方法
Java核心技术卷一 -第五章:数组列表初识
Java核心技术卷一 -第五章:装箱和拆箱
Java核心技术卷一 -第五章:枚举类再认识
Java核心技术卷一 -第七章:异常
前言
本人为java初学者,文章内容仅为个人学习总结分享,其中包含了大量Java核心技术卷一里面的文章内容以及一些网站文章内容,由于参考文章过多,在此并不一一列出,如有侵权,请联系删除。
一、集合概述
1.1、什么是集合?有什么用?
数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。
集合为什么说在开发中使用较多?
集合是一个容器,是一个载体,可以一次容纳多个对象。在实际开发中,假设连接数据库,数据库当中有10条记录,那么假设把这10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将一个数据一个
数据展现出来。
1.2、集合不能直接存储基本数据类型,另外集合也不能直接存储java对象
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)
list.add(100);//自动装箱Integer,里面存储的并不是100,而是一个装箱对象
注意:
- 集合在java中本身是一个容器,是一个对象,其也有内存地址。同样也可能有某一个变量指向集合,里面存储着集合的地址。
- 集合中任何时候存储的都是“引用”。
图示:
1.3、在java中每一个不同的集合,底层会对应不同的数据结构
往不同的集合中存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的结构就是数据结构。不同的数据结构,数据存储方式不同。
例如:数组、二叉树、链表、哈希表,,,,,,,
以上这些都是常见的数据结构。
你往集合1中放数据,可能是放到数组上了
你往集合2中放数据,可能是放到二叉树上了。
你使用不同的集合等同于使用了不同的数据结构。
提示:
在java集合这一章节,需要掌握的不是精通数据结构。java中已经将数据结构实现了,已经写好了这些常用的集合类,我们只需要掌握怎么用?在什么情况下选择哪一种合适的集合去使用即可。
new ArrayList();创建一个集合,底层是数组.
new LinkedList();创建一个集合对象,底层是链表.
new Treeset();创建一个集合对象,底层是二又树.
1.4、集合在java JDK中哪个包下?
java.util.*;
所有的集合类和集合接口都在java.util包下。
1.5、在java中集合分为两大类
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;
一类是以键值对儿的方式存储元素:
以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;
1.6、集合的继承结构图
Collection类:
提示:Collection通过调用Iterable中的iterator方法可以得到一个Iterator迭代器
Map类:
1.7、小总结
二、Collection接口类
2.1、Collection接口的常用方法
关于java.util.Collection接口中常用的方法:
Collection中能存放什么元素?
没有使用“泛型”之前,Collection中可以存储Object的所有子类型。使用了“泛型”之后,Collection中只能存储某个具体的类型。
集合后期我们会学习“泛型语法。目前先不用管。Collection中什么都能存。
只要是Object的子类型就行。(集合中不能直接存储基本数据类型,也不能存java对象,只是存储java对象的内存地址。)
Collection中的常用方法
boolean add(Object e)向集合中添加元素
int size()获取集合中元素的个数
void clear()清空集合
boolean contains(object o)判断当前集合中是否包含元素。,包含返回true,不包含返回false boolean
remove(object o)删除集合中的某个元素
boolean isEmpty()判断该集合中元素的个数是否为0
object[]toArray()调用这个方法可以把集合转换成数组
代码展示:
import java.util.ArrayList;
import java.util.Collection;
public class Test02 {
public static void main(String[] args) {
//创建一个集合对象
//Collection c = new Collection();//接口是抽象的,无法实例化。
//多态
Collection c = new ArrayList();
//测试Collection接口中的常用方法
c.add(1200);//自动装箱(java5的新特性。),实际上是放进去了一个对象的内存地址。Integer x=new Integer(1200);
c.add(3.14);//自动装箱
c.add(new Object());
c.add(new Student());
c.add(true);//自动装箱
//获取集合中元素的个数
System.out.println("集合中元素的个数是:"+c.size());//5
//清空集合
c.clear();
System.out.println("集合中元素的个数是:"+c.size());//0
//再向集合中添加元素
c.add("hello");
c.add("world");
c.add("飞机");
c.add("飞上天");
c.add(1);
//判断集合中是否包含“飞机”
boolean flag=c.contains("飞机");//true
System.out.println(flag);
//判断集合中是否包含“飞机2”
boolean flag2=c.contains("飞机2");//false
System.out.println(flag2);
//删除集合中某个元素
c.remove(1);
System.out.println("集合中元素的个数是:"+c.size());//4
//判断集合是否为空(集合中是否存在元素)
System.out.println(c.isEmpty());//false
//清空
c.clear();
System.out.println(c.isEmpty());//true(true表示集合中没有元素了!)
c.add("abc");
c.add("def");
c.add(100);
c.add("helloworld!");
c.add(new Student());
//转换成数组
Object[] objs=c.toArray();
for (int i=0;i< objs.length;i++){
//遍历数组
Object o=objs[i];
System.out.println(o);
}
}
}
class Student{
}
结果:
2.2、迭代器
代码展示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test02 {
public static void main(String[] args) {
//注意:以下讲解的遍历方式/迭代方式,是所有Collection通用的一种万式,
//Map集合中不能用。在所有的Collection以及子类中使用。
//创建一个集合对象
Collection c = new ArrayList();
//添加元素
c.add("abc");
c.add("def");
c.add(100);
c.add("helloworld!");
c.add(new Student());
//对集合Collection进行遍历/送代
//第一步:获取集合对象的迭代器对象Iterator
Iterator it=c.iterator();
//第二步:通过以上获取的迭代器对象开始好迭代/遍历集合。
/*
以下两个方法是迭代器对象Iterator中的方法:
boolean hasNext()如果仍有元素可以迭代,则返回true。
Object next()返回迭代的下一个元素。
*/
while (it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
}
}
class Student{
}
结果:
类似过程图说明:
2.3、深入Collection集含的contains方法
boolean contains(Object o)
判断集合中是否包含某个对象。
如果包含返回true,如果不包含返回false。
contains方法是用来判断集合中是否包含某个元素的方法,那么它在底层是怎么判断集合中是否包含某个元素的呢?
调用了equals方法进行比对。
equals方法返回true,就表示包含这个元素。
注意:
由于contains方法底层调用的是equals方法,而String的equals方法比较的是内容而不是地址,所以实验结果为true,但x确实不在集合中。
其它的equals方法没有重写,比较的可能是地址,这样子结果就为false了,请注意!!!
代码展示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test02 {
public static void main(String[] args) {
//创建一个集合对象
Collection c = new ArrayList();
//向集合中存储元素
String s1=new String("abc");//假设s1存储的地址为0x1111
c.add(s1);
String s2=new String("def");//假设s2存储的地址为0x2222
c.add(s2);
//集合中元素的个数
System.out.println("元素的个数是:"+c.size());//2
//新建的对象String
String x=new String("abc");//假设x存储的地址为0x5555
//c集合中是否包含x?
System.out.println(c.contains(x));//true
}
}
结果:
代码结构图:
2.4、状态改变下的迭代器
提醒:
迭代器相当于一个快照,记录拍下了那一瞬间的集合,如果冒然动用删除、增加方法会导致那张快照与集合不符,而迭代器会经常比较二者,一旦不同,则会抛出异常,所以在集合改变后一定要重新获取迭代器,或者动用迭代器中的输出方法,因为它会将快照与集合中的元素都删除,这样便不会出现异常。
重点:
当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前老的迭代器,会出现异常:javautil.ConcurrentModificationException
重点:
在迭代集合元素的过程中,不能调用集合对象的remove、add方法,删除、增加元素,会出现:java.util.ConcurrentModificationException
代码展示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test02 {
public static void main(String[] args) {
//创建一个集合对象
Collection c = new ArrayList();
//向集合中存储元素
c.add("abc");
c.add("def");
c.add("xyz");
Iterator it=c.iterator();
while (it.hasNext()){
Object o=it.next();
//删除元素
//删除元素之后,集合的结构发生了交化,应该重新去获取迭代器
//但是,循环下一次的时并没有重新获取迭代器,所以会出现异常;jovo,utt,Concurrenth odificotionExce
//c.remove(o);//直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照和原集合状态不同。)
//使用迭代器来删除可以吗?
it.remove();//删除一定是迭代器指向的当前元素。
System.out.println(o);
}
System.out.println(c.size());
}
}
图示:
三、泛型
1、JDK5.之后推出的新特性:泛型
2、泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的。(运行阶段泛型没用!)
3、使用了泛型好处是什么?
第一:集合中存储的元素类型统一了。
第二:从集合中取出的元素类型是泛型指定的类型,不需进行大量的“向下转型”!
4、泛型的缺点是什么?
导致集合中存的元素缺乏多样性!
5、大多数业务中,集合中元素的类型还是统一的。所以这种泛型特性被大家所认可。
没用泛型之前
代码展示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class Test02 {
public static void main(String[] args) {
//不使用泛型机制,分析程序存在缺点
List myList = new ArrayList();
//准备对象
Cat c = new Cat();
Bird b = new Bird();
//将对象添加到集合当中
myList.add(c);
myList.add(b);
//遍历集合,取出每个Animal,让它move
Iterator it = myList.iterator();
while (it.hasNext()) {
//没有这个语法,通过迭代器取出的就是Object
//Animal a = it.next();
Object obj = it.next();
//obj中没有move方法,无法调用,需要向下转型!
if (obj instanceof Animal){
Animal a = (Animal) obj;
a.move();
}
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠!");
}
}
class Bird extends Animal{
public void fly(){
System.out.println("鸟儿在飞翔!");
}
}
结果:
用泛型之后
代码展示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class Test02 {
public static void main(String[] args) {
//使用JDK5之后的泛型机制
//使用泛型ist<Animal>之后,表示list集合中只允许存Animal类型的数据。
// 用泛型来指定集合中存储的数据类型。
List<Animal> myList = new ArrayList<Animal>();
//指定list集合中只能存储Animal,那么存储String就编译报错了。
//这样用了泛型之后,集合中元素的数据类型更加统一了。
//myList.add("abc");
//准备对象
Cat c = new Cat();
Bird b = new Bird();
//将对象添加到集合当中
myList.add(c);
myList.add(b);
//获取迭代器
//这个表示迭代器的是Animal类型.
Iterator<Animal> it = myList.iterator();
while (it.hasNext()) {
//调用子类特有的方法还是需要向下转换的!
Animal k=it.next();
k.move();
if (k instanceof Cat){
Cat x=(Cat)k;
x.catchMouse();
}
if (k instanceof Bird){
Bird y=(Bird)k;
y.fly();
}
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠!");
}
}
class Bird extends Animal{
public void fly(){
System.out.println("鸟儿在飞翔!");
}
}
结果:
自定义泛型
自定义泛型可以?
可以
自定义泛型的时候,<>尖括号中的是一个标识符,随使写。java源代碍中经常出现的是:E、T
E是Element单词首字母。
T是Type单词首字母。
代码展示:
public class Test02<标识符随便写> {
public void doSome(标识符随便写 o){
System.out.println(o);
}
public static void main(String[] args) {
//new对象的时候指定了泛型是:String类型
Test02<String> gt=new Test02<String>();
//类型不匹配
//gt.doSome(100);
gt.doSome("abc");
//================================================================
Test02<Integer> gt2=new Test02<>();
gt2.doSome(100);
}
}
结果:
四、foreach
一种比普通for循环方便的遍历方式
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//new对象的时候指定了泛型是:String类型
List<String> stringList= new ArrayList();
//添加元素
stringList.add("hello");
stringList.add("world!");
stringList.add("key!!");
//遍历,使用迭代器方式
Iterator<String> it=stringList.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println(s);
}
//使用下标的方式(只针对于有下标的集合)
for (int i=0;i<stringList.size();i++){
System.out.println(stringList.get(i));
}
//使用foreach
for (String z:stringList){
System.out.println(z);
}
}
}
五、Map
5.1、Map接口常用的方法:
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//创建Map集合对象
Map<Integer,String> map=new HashMap<>();
//向Map集合中加键值对
map.put(1,"zhangsan");//1在这里进行了自动装箱。
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//遇过key获成value
String value = map.get(2);
System.out.println(value);
//获取键值对的数量
System.out.println("健值对的数量:"+map.size());
//通过key删除key-value
map.remove(2);
System.out.println("键值对的数量:"+map.size());
//判断是否包含某个key
//contains方法底层用的都是equals进行比对的,所以自定义的类型要写equals方法。
System.out.println(map.containsKey(new Integer(4)));//true
//判断是否包含某个value
System.out.println(map.containsValue(new String("wangwu")));//true
//获取所有的value
Collection<String> values=map.values();
for(String s:values) {
System.out.println(s);
}
//清空Map集合
map.clear();
System.out.println("键值对的数量:"+map.size());
//判断是否为空I
System.out.println(map.isEmpty());//true
}
}
结果:
5.2、遍历Map集合
第一种:通过遍历,获取所有的key,通过key获取value
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//创建Map集合对象
Map<Integer,String> map=new HashMap<>();
//向Map集合中加键值对
map.put(1,"zhangsan");//1在这里进行了自动装箱。
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//遍历Nap集合
//获取所有的key,所有的物key是一个set集合
Set<Integer>keys =map.keySet();
//遍历key,通过key获取value
//迭代器方法
Iterator<Integer>it =keys.iterator();
while(it.hasNext()) {
//取出其中一个key
Integer key = it.next();
//通过key获取value
String value = map.get(key);
System.out.println(key + "=" + value);
}
}
}
结果:
第二种:通过map.entrySet()方法
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//创建Map集合对象
Map<Integer,String> map=new HashMap<>();
//向Map集合中加键值对
map.put(1,"zhangsan");//1在这里进行了自动装箱。
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//遍历Nap集合
//通过map.entrySet()方法
Set<Map.Entry<Integer,String>> set=map.entrySet();
//迭代器方法
Iterator<Map.Entry<Integer,String>> it2 =set.iterator();
while(it2.hasNext()) {
Map.Entry<Integer,String> node=it2.next();
Integer key=node.getKey();
String value=node.getValue();
System.out.println(key + "=" + value);
}
}
}
结果:
5.3、Properties属性类
只需要掌握Properties属性类对象的相关方法即可。
Properties是一个Map集合,继承Hashtable,Properties的key value都String类型。Properties被称为属性类对象。Properties.是线程安全的。
代码展示:
结果:
5.4、TreeSet
1、TreeSet集合底层实际上是一个TreeMap
2、TreeMap集合底层是一个二交树
3、放TreeSet集合中的元素,等同于放TreeMap集合key部分了。
4、TreeSet集合中的元素:无序不可重复。但是可以按照元素的大小顺序自动序。称为:可排序集合。
图示:
5、TreeSet无法对自定义类型排序,除非实现Comparable接口
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//创建TreeSet集合对象
TreeSet<Integer> ts =new TreeSet<>();
//向ts集合中加字
ts.add(100);//100在这里进行了自动装箱。
ts.add(900);
ts.add(500);
ts.add(300);
ts.add(700);
ts.add(800);
ts.add(10);
ts.add(50);
//遍历ts集合
for (Integer s:ts){
System.out.println(s);
}
}
}
结果:
六、Collections工具类
6.1、Collections工具类的用处
(1):让线程变成安全的:
代码展示:
import java.util.*;
public class Test02 {
public static void main(String[] args) {
//创建集合对象
//ArrayList集合不是线程安全的
List<String> list=new ArrayList<>();
//变成线程安全的
Collections.synchronizedCollection(list);
//加入元素
list.add("abf");//100在这里进行了自动装箱。
list.add("abx");
list.add("abc");
list.add("abe");
list.add("zxc");
//排序
Collections.sort(list);
//遍历集合
for (String s:list){
System.out.println(s);
}
}
}
结果:
(2):给不同集合排序,不同的集合可以先通过转换成ArrayList集合,再排序:
代码展示:
结果:
七、集合总结
7.1、集合这块最主要掌握什么内容?
1、每个集合对象的创建(new)
2、向集合中添加元素
3、从集合中取出某个元素
4、遍历集合
5、主要的集合类:
ArrayList
LinkedList
HashSet (HashMap的key,存储在HashMap集合key的元素需要同时重写hashCode+equals)
Treeset
HashMap
Properties
TreeMap
代码展示(以ArrayList为例):
结果:
代码展示(以 HashSet为例):
结果:
代码展示(以 Treeset 为例):
结果:
代码展示(以HashMap为例):
结果:
代码展示(以Properties为例):
结果:
总结
以上就是本文的内容,记录了一些关于java“集合”的内容,本人也是刚开始接触java,不能保证总结内容的正确性,若是有错误的话,欢迎大家指出,谢谢!