java入门基础二 15-18 之三大集合

Day15集合值框架

数组:部分集合的底层是用数组写的;

基本数据类型存储的是值,

引用数据类型 中存储的不是对象,是对象的地址值。

数组与集合的区别:

1. 数组 可以存储基本数据类型,也可以存储引用数据类型,基本数据类型存储值,引用数据类型存储地址值。

集合只能存储引用数据类型(对象)。集合中也可以存储基本数据类型,但是在存储的时候会自动装箱成对象。

2. 数组的长度是固定的,不能自动增长;

集合的长度是可变的。可以随着元素的增加而增长;

什么情况下使用数组或者集合:

如果元素的个数是固定的使用数组(效率高);

如果元素的个数是变化的使用集合。

Collection(单列集合的跟接口)

 

List集合: 有序(存和取是有序的),有序列,可以存储重复元素

1. ArrayList 集合:数组实现。 查询块,修改也快,增删慢

2. LinkedList集合:链表实现。查询慢,修改也慢,增删快

Set集合:无序(存和取是无序的) ,无序列,不能存储重复元素。

1. HashSet集合:哈希算法,

2. TreeSet集合:二叉树算法,

Collection集合

add(E e)方法

Collection c = new ArrayList();

boolean b1 = c.add("abc");

boolean b2 = c.add(true);

boolean b3 = c.add(100);

boolean b4= c.add(new Student(23,"zs" ));

//add方法如果是List集合一直都返回ture;因为List集合是可以存储重复元素的;

//add方法如果是set集合当存储重复元素的时候,就会返回false;

//ArrayList的爷爷类重写toString方法,所以在打印对象引用的时候,输出的结果不是Object类中的toString结果;

remove(Object o)方法 、 clear()方法 、 contains()方法 、 isEmpty()方法 、size()方法

Collection c = new ArrayList();

c.add("a");

c.add("b");

c.add("c");

c.remove("b"); //删除指定元素

System.out.println(c); //输出 : [a, c]

System.out.println(c.contains("b")); // 判断是否包含 输出: true

c.clear(); //清空集合

System.out.println(c); //输出: []

System.out.println(c.isEmpty()); //判断是否为空 空返回 true,非空返回false

System.out.println(c.size()); //判断集合的个数

集合转换成数组

Collection c = new ArrayList();

c.add("a");

c.add("b");

c.add("c");

Object[] array = c.toArray(); //将集合转换成数组

for (int i = 0; i < array.length; i++) { //遍历数组

System.out.println(array[i]);

}

Collection c = new ArrayList();

c.add( new Student(23,"zs")); //相当于 Object obj = new Student();

c.add( new Student(24,"zs")); //自动向上转型,类型提升

c.add( new Student(25,"zs"));

Object[] arr = c.toArray(); //将对象转换成数组,

for(int i=0; i< arr.length; i++){ //遍历

Student s = (Student)arr[i]; //在向下转型 多态的缺点 不能使用子类特有的属性或方法

System.out.println(s.getName()+"--"+s.getAge());

}

Collection 的 add()方法 和 addAll() 方法区别

Collection c = new ArrayList();

c.add("a");

c.add("b");

c.add("c");

Collection c1 = new ArrayList();

c1.add("a");

c1.add("b");

c1.add("c");

c.addAll(c1); // 将c1中的每一个元素添加到c中 输出: [a, b, c, a, b, c]

c.add(c1); //把c1集合看成一个对象 添加到c中 输出: [a, b, c, [a, b, c]]

System.out.println(c);

removeAll()方法 删除的交集 containsAll()方法 判断是否包含传入的集合

Collection c = new ArrayList();

c.add("a");

c.add("b");

c.add("c");

Collection c1 = new ArrayList();

c1.add("a");

c1.add("b");

boolean b = c.removeAll(c1); //从c中删除 c1,删除的交集

boolean b = c.containsAll(c1); //判断是否包含传入的集合

System.out.println(b);

System.out.println(c); //输出 [c]

retainAll()方法 取交集

Collection c = new ArrayList();

c.add("a");

c.add("b");

c.add("c");

Collection c1 = new ArrayList();

c1.add("a");

c1.add("b");

c1.add("c");

c1.add("d");

boolean b = c.retainAll(c1); //取交集, 把c1付给c 就看调用的集合是否改变

//取交集, 如果调用的交集改变就返回true , 如果调用的集合没改变就返回false

System.out.println(b); //false

System.out.println(c); //[a, b, c]

集合的迭代器遍历 Iterator

迭代器概述:集合是用来存储元素的,存储元素就需要查看,那么就需要迭代(遍历)

hasNext()方法 //判断是否有元素,如果有就返回true。

next()方法 返回迭代的下一个元素。重复调用此方法直到 hasNext() 方法返回 false

Collection c = new ArrayList();

c.add(new Student(23,"张三"));

c.add(new Student(24,"张三"));

c.add(new Student(25,"张三"));

Iterator it = c.iterator();

while(it.hasNext()){
Student s = (Student)it.next();

System.out.println(s.getName()+"--"+s.getAge());

}

List集合特有的 功能概述

add()方法:

List l = new ArrayList();

l.add("a");

l.add("b");

l.add("c");

l.add(5,"d"); //index = 0,否则会报下标越界异常

System.out.println(l); //输出: IndexOutOfBoundsException

remove()方法

List l = new ArrayList();

l.add(111);

l.add(222);

l.add(333);

l.add(444);

l.remove(111); //删除指的是下标 , 不是指的对象 把111看成了下标 不是对象

System.out.println(l); //IndexOutOfBoundsException 不会自动装箱

get()方法

List l = new ArrayList();

l.add(111);

l.add(222);

l.add(333);

l.add(444);

Object obj = l.get(8); //get(下标) :下标不能大于size,否则报下标越界异常

System.out.println(obj);

for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i)); // 通过索引获取每一元素

}

set()方法

List l = new ArrayList();

l.add(111);

l.add(222);

l.add(333);

l.add(444);

l.set(1,666);

System.out.println(l); //输出: [111, 666, 333, 444]

ListIterator() 方法的使用

List l = new ArrayList();

l.add("a"); //自动类型提升object

l.add("world"); //相当于 Object obj = new String();

l.add("f");

l.add("b");

/* Iterator it = l.iterator();

while(it.hasNext()){ //判断集合中是否有元素

String str = (String) it.next(); //强制类型转换String

if(str.equals("world")){
l.add("javaee"); //在遍历的同时添加元素,并发修改

}

}

System.out.println(l);//输出:并发修改异常 ConcurrentModificationException*/

listIterator()方法 可以实现在遍历的同时添加元素

ListIterator lit = l.listIterator(); //利用listIterator特有的方法可以实现

while(lit.hasNext()){ //判断集合中是否有元素

String str = (String) lit.next(); //强制类型转换String

if(str.equals("world")){
lit.add("javaee"); //在遍历的同时添加元素,并发修改

}

}

System.out.println(l);//输出:[a, world, javaee, f, b]

集合框架数据结构之数组和链表

List的三个子类的特点: 存储的都是对象的地址值;

ArrayList: 底层数据结构是数组,查询块,修改也快,增删慢。线程不安全,效率高

查询和修改快的原因:底层是数组,直接通过下标找值,所以非常快,数组最大值是 size - 1,

增删慢的原因:在某个位置添加元素,后面的其他所有元素需要向后移动下标,过程比较复杂, 所以

添加 较慢,当删除某个元素的时候,其后面的所有元素需要向前移动下标,所以删除较慢。

图形讲解原理图:

 

Vector: 底层数据结构是数组,查询块,增删慢,线程安全,效率低。

LinkedList:底层数据结构是链表,查询慢,修改也慢,增删快,线程不安全,效率高

查询和修改慢的原因:底层是链表结构,需要一个一个的去查找(从前向后或者从后向前),率相对较低,

增删快的原因:在某个位置添加元素,直接在两个元素中间断开插入后在两两相互连接即可,所以较快。

删除某个元素即前后连接断开后移除,之后相邻的元素在连接即可。所以较快

图形讲解原理图:

size >> 1 代表除以2, size 的 一次幂; 如图所示

 

Day16List集合框架

去除ArrayList集合中的重复字符串元素方式

ArrayList l = new ArrayList(); //创建旧集合

l.add("a");

l.add("a");

l.add("b");

l.add("b");

l.add("v");

l.add("v");

ArrayList li = getlist(l); //调用新集合

System.out.println(li);

}

public static ArrayList getlist(ArrayList l){
ArrayList newlist = new ArrayList(); //创建集合

Iterator it = l.iterator(); //根据传入的集合(旧集合)获取迭代器

while(it.hasNext()){ //遍历旧集合

Object obj = it.next(); //记录每一个集合

if(!newlist.contains(obj)){ //判断新集合是否包含旧集合

newlist.add(obj); //向新集合添加元素

}

}

return newlist;

}

contains() 方法: 判断是否包含,底层依赖的是equals方法;

remove() 方法: 判断是否删除,底层依赖的是equals方法

LinkedList() 的特有功能

LinkedList l = new LinkedList(); //dcbaw

l.addFirst("a"); //从第一个位置添加,每次添加都是从第一个位置添加

l.addFirst("b");

l.addFirst("c");

l.addFirst("d");

l.addLast("w"); //从最后一个位置添加,每次添加都是从最后一个位置添加

System.out.println(l); //输出:[d, c, b, a, w]

System.out.println(l.getFirst()); //获取第一个元素 d

System.out.println(l.getLast()); //获取最后一个元素 w

System.out.println(l.removeFirst()); //移除第一个元素 d

System.out.println(l.removeLast()); //移除最后一个元素 w

System.out.println(l);//输出 : [c, b, a]

//dcbaw

System.out.println(l.get(2)); //输出: a

泛型

泛型的概述:

泛型基本使用 :

<>中放的必须是引用数据类型

泛型的好处:

1、提高安全性(将运行期的错误转换到编译期)

2、省去强转的麻烦

泛型什么时候赋值

非静态方法在创建对象的时候,静态方法在调用静态方法的时间赋值

 

案例:

//不加泛型

ArrayList l = new ArrayList();

l.add(100);

l.add(true);

l.add(new Student(23,"张三"));

Iterator it= l.iterator();

while(it.hasNext()){
Student obj =(Student)it.next(); //向下强制 转型 会报类转换异常 ClassCastException

System.out.println(obj);

}*/

//加泛型

//int[] arra = new int[5]; //数组要保证前后数据类型一致。

ArrayList l = new ArrayList(); //集合的泛型要保证前后的数据类型一致;

// l.add(100); //添加泛型后编译不同过,报错

// l.add(true);

l.add(new Student(23,"张三"));

l.add(new Student(24,"李四"));

Iterator it= l.iterator();

while(it.hasNext()){
Student obj = it.next(); //不用强砖

System.out.println(obj.getName()+"--"+obj.getAge());

// System.out.println(it.next().getName()+"--"+it.next().getAge()); //输出:错误的值 张三--24

// next()方法只能调用一次,如果调用多次会将指针向后移动多次;

}

泛型的基本使用:

泛型使用的注意事项:

//int[] arra = new int[5]; //数组要保证前后数据类型一致。

ArrayListStudent> l = new ArrayListStudent>(); //集合的泛型要保证前后的数据类型一致;

ArrayListObject> ls = new ArrayList<>();//1.7版本新特性,菱形泛型, 泛型最好不要定义成Object,没有意义

向泛型中添加对象 : Person

泛型方法的概述和使用 :

public class ToolQ> {
private Q q;

public Q getQ() {
return q;

}

public void setQ(Q q) {
this.q = q;

}

public void show(Q q){ //Q q在创建对象的时候才有值,即new的过程。

System.out.println(q); //方法泛型最好与类的泛型一致

}

public void show1(T t){ //如果不一致,需要在方法上声明该泛型

System.out.println(t);

}

public static void show2(W w){//q在调用静态方法的时候才会赋值

//因为静态方法时随着类加载而创建,所以静态必须声明自己的泛型

System.out.println(w);

}

泛型接口的概述和使用

interface Inter{ //定义一个接口

public void show(T t);

}

class demo implements Inter{ //实现这个接口

@Override

public void show(String t) {
System.out.println(t);

}

}

泛型高级之通配符:

//* B:? extends E, B是子类、 E是父类 向下限定,E及其子类

public static void main(String[] args) {
List l = new ArrayList();//当左边的泛型是不确定时,左边可以指定为?

增强for循环:

for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素

}

因为底层是迭代器实现:所以增强for循环不能删除,只能遍历。要是删除会出现 并发修改异常 快捷键输入 fore Art+/

三种遍历方式能否删除

ArrayList list = new ArrayList<>();

list.add("a");

list.add("b");

list.add("b");

list.add("c");

list.add("d");

普通for循环 当两个元素相邻时,要删除这些元素要通过索引 --来完成

for(int i = 0; i < list.size(); i++) {
if("b".equals(list.get(i))) {
list.remove(i--); //通过list集合的索引删除元素

}

}

//2,迭代器删除

Iterator it = list.iterator();

while(it.hasNext()) {
if("b".equals(it.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常

it.remove();//只能通过迭代器自身的remove方法

}

}

//3,增强for循环,增强for循环不能删除,只能遍历

for (String string : list) {
if("b".equals(string)) {
list.remove("b");

}

}

System.out.println(list);

}

Day17Set集合框架

HashSet hs = new HashSet();

boolean add = hs.add("a"); //不能存储重复元素

boolean add2 = hs.add("a");

System.out.println(hs); //输出:[a]

hs.add("a");

hs.add("b");

hs.add("c"); //是无序的

System.out.println(hs); //输出:[b, c, a]

迭代器遍历

for (String string : hs) {
System.out.println(string); //只要能用迭代器迭代的,就可以使用增强for循环遍历。

}

只有HashCode方法一样的时候才会调用equals方法。

HashCode方法里面的常量为什么是31

/*

* 为什么是31;

* 1.31是质数 。只能被1和本身整除

* 2.31既不大也不小,大了 计算有可能超过int取值范围,小了 重复概率就大了。

* 3.31这个数好计算,2的5次方减1,2向左移动5位

*/

@Override

public int hashCode() {
final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((name == null) ? 0 : name.hashCode());

return result;

}

LinkedHashSet()方法 的概述和使用:

底层是链表实现的,是set集合唯一一个能保证怎么存就怎么取的集合对象;

因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样

TreeSet()集合:

TreeSet集合是用来对象元素进行排序的,也可以保证元素唯一的。

TreeSet()集合基本没怎么学,有时间重新学;

day18MAP集合

map集合概述和特点:

map是双列的,coolection是单列的,

map的键是唯一的,Coolection的字体系set是唯一的;

map集合的数据结构值针对有效,跟值无关,Collection集合的数据结构是真对元素有效的

Set的底层依赖的是Map

Map集合的功能类概述:

map底层是Hash算法,不能保证怎么存的怎么取,

Map集合的添加方法put()

Map m = new HashMap<>();

m.put("张三", 23); //map底层是Hash算法,不能保证怎么存的怎么取,

m.put("李四", 24);

m.put("王五", 25);

m.put("王五", 26); //相同的键不存储,值被覆盖。

System.out.println(m);

remove()删除方法

Integer remove = m.remove("张三"); //根据键删除元素,返回对应的值

System.out.println(remove);

containsKey()方法 判断是否包含传入的键

boolean containsKey = m.containsKey("张三");

System.out.println(containsKey); //判断是否包含传入的键

containsValue()方法 判断是否包含传入的值

boolean containsValue = m.containsValue(23);

System.out.println(containsValue); //判断是否包含传入的值

isEmpty()方法 判断是否包为空

boolean empty = m.isEmpty();

System.out.println(empty); //判断是否包为空。是空返回true,非空返回false

values()方法获取集合的所有值

Collection values = m.values();

System.out.println(values); // values()方法获取集合的所有值

System.out.println(m.size()); //返回集合中的键值对的个数

map集合是不能直接迭代的, map集合的遍历

Map m = new HashMap<>();

m.put("张三", 23);

m.put("李四", 24);

m.put("王五", 25);

m.put("周六", 26);

//用迭代器遍历

Set keySet = m.keySet(); //获取所有的键 把键存储到set集合中

Iterator it = keySet.iterator(); //获取迭代器

while(it.hasNext()){ //判断集合中是否有元素

String key = it.next(); //获取每一个键

Integer integer = m.get(key); //根据键获取值

System.out.println(integer);

}

//通增强for遍历

for (String key : m.keySet()) { //m.keySet()是所有键的集合

Integer value = m.get(key); //根据键获取值

System.out.println(key+"=="+value);

}

map集合的第二种遍历方式; 根据键值对的对象 获取键和值

Map map = new HashMap<>();

map.put("张三", 23);

map.put("李四", 24);

map.put("王五", 25);

map.put("周六", 26);

迭代器遍历

//Map.Entry(K,V); Entry是Map接口里面的子接口 ,

//将键和值封装成Entry对象,(类似于Person对象),并存储在Set集合中

Set> entrySet = map.entrySet(); //将键和值封装成对象

Iterator> it = entrySet.iterator(); //获取迭代器,获取每一个对象

while(it.hasNext()){ //判断集合中是否有对象

// Map.Entry next1 = it.next(); //记录每一对象, 父类引用指向子类对象

Entry next = it.next(); //记录每一对象, 直接获取的是子类对象

//Entry 继承并重写了 Map.Entry,

String key = next.getKey(); //获取键

Integer value = next.getValue(); //获取值

System.out.println(key+"==="+value);

}

增强For循环遍历

for(Map.Entry ma : map.entrySet() ){
System.out.println(ma.getKey()+"==="+ma.getValue());

}

练习: 案例演示

* 需求:统计字符串中每个字符出现的次数

String str = "aaaabbbcccccccccc";

char[] arr = str.toCharArray(); //将字符串转换成字符数组

HashMap hm = new HashMap<>(); //创建双列集合存储键和值

for(char c : arr) { //遍历字符数组

/*if(!hm.containsKey(c)) { //如果不包含这个键

hm.put(c, 1); //就将键和值为1添加

}else { //如果包含这个键

hm.put(c, hm.get(c) + 1); //就将键和值再加1添加进来

}*/

hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1); //使用三元运算符,简单

}

for (Character key : hm.keySet()) { //遍历双列集合

System.out.println(key + "=" + hm.get(key));

}

HashMap 和 HashTable 的区别

共同点: 底层都是哈希算法,都是双列集合;

区别: 1、HashMap是线程不安全的,效率高;Hashtable是线程安全的,效率低

2、HashMap可以有空键空值;hashtable不可以存储空键和空值。

集合框架 Collections工具类;

Collections成员方法

public static void sort(List list) //排序

public static int binarySearch(List list,T key) //二叉法

public static T max(Collection coll) //先默认排序,再获取最大值

public static void reverse(List list) //反转输出

public static void shuffle(List list) //随机置换,可以用来洗洗牌。

代码如下:

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值