javaday12
目录
Day12--集合+泛型... 1
1 List接口... 1
1.1 概述... 1
1.2 特点... 1
1.3 常用方法... 1
1.4 练习1:测试常用方法... 3
2 ArrayList. 3
2.1 概述... 3
2.2 创建对象... 3
2.3 练习1:测试常用方法... 3
3 LinkedList. 4
3.1 概述... 4
3.2 创建对象... 4
3.3 常用方法... 4
3.4 练习1:测试常用方法... 4
4 Set接口... 5
4.1 概述... 5
4.2 特点... 5
4.3 常用方法... 5
4.4 练习1:测试常用方法... 5
5 HashSet. 5
5.1 概述... 5
5.2 练习1:测试常用方法... 6
6 Map接口... 6
6.1 概述... 6
6.2 特点... 6
6.3 继承结构... 7
6.4 常用方法... 7
6.5 练习1:测试常用方法... 7
7 HashMap.. 8
7.1 概述... 8
7.2 练习1:获取HashMap的数据... 8
7.3 练习2:字符串中的字符统计... 9
8 扩展... 9
8.1 了解栈和队列... 9
8.2................................................................................. Set存储属性相同的对象... 9
Day12--集合+泛型
1 List接口
1.1 概述
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
1.2 特点
1、 数据有序
2、 允许存放重复元素
1.3 常用方法
ListIterator<E> listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<E> listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
List<E> subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
E get(int index)
返回列表中指定位置的元素。
1.4 练习1:测试常用方法
package cn.tedu.collection;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
//测试List接口
public class Test7_List {
public static void main(String[] args) {
//1、创建对象
//List是接口
List<Integer> list = new ArrayList<>();
//2、常用方法
list.add(100);
list.add(101);
list.add(102);
list.add(103);
list.add(102);
list.add(105);
System.out.println(list);
// list.clear();
System.out.println(list.contains(100));
System.out.println(list.equals(101));
System.out.println(list.hashCode() );
System.out.println( list.isEmpty() );
System.out.println(list.remove(2) );
System.out.println(list.size() );
System.out.println(list.toArray() );
//特有方法
System.out.println(list+"======");
System.out.println( list.indexOf(105) );
System.out.println(list.lastIndexOf(102) );
list.add(3,105);
System.out.println(list);
System.out.println(list.get(3));
System.out.println(list.set(0,99));
System.out.println(list);
System.out.println(list.subList(2, 4));//含头不含尾,类似于String.subString()
System.out.println(list);
//遍历集合中元素
//ListIterator继承了Iterator,并提供了更加完善的功能,除了正常向后遍历还增加了向前遍历的功能
ListIterator it = list.listIterator();
while(it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
}
//TODO 子接口提供的遍历方式-如:向前遍历
}
}
2 ArrayList
2.1 概述
1) 存在于java.util包中。
2) 内部用数组存放数据,封装了数组的操作,每个对象都有下标。
3) 内部数组默认初始容量是10。如果不够会以1.5倍容量增长。
4) 查询快,增删数据效率会降低。
2.2 创建对象
ArrayList()
构造一个初始容量为 10 的空列表。
ArrayList(int initialCapacity)
构造一个具有指定初始容量的空列表。
2.3 练习1:测试常用方法
创建day12工程
创建cn.tedu.arraylist包
创建Test1_ArrayList.java
下标遍历,迭代器遍历
package cn.tedu.arraylist;
import java.util.ArrayList;
import java.util.Iterator;
//测试ArrayList常见方法
//总结:
//1, ArrayList 底层就是个数组的结构,数据默认初始容量是10
//2, ArrayList 元素都有下标 , 元素可重复 , 元素有序
//3, 遍历元素时可以使用 迭代器遍历 ,普通for循环遍历 ,增强for循环/foreach结构
//4, 默认的扩容方式是原来的1.5倍: int newCapacity = oldCapacity + (oldCapacity >> 1);
public class Test1_ArrayList {
public static void main(String[] args) {
//1、创建ArrayList对象
//特点1:底层维护了Object[] , 初始容量是10
ArrayList<String> list = new ArrayList<>();
//2、常用方法
//特点2:元素都有索引 + 元素可重复 + 有序数据
list.add("张三");
list.add("李四");
list.add("如花");
list.add("石榴姐");
list.add("李四");
list.add("张三");
System.out.println(list);
//遍历元素
//用迭代器遍历
Iterator it = list.iterator();
while(it.hasNext()) {//判断,有元素的话返回true,去获取值
Object obj = it.next();
String str = (String) obj;
System.out.println(str);
}
System.out.println();
//用下标遍历
//list.size() -- 集合的长度(元素的个数)
for(int i = 0 ; i < list.size() ; i++ ) {
//list.get(i) -- 根据下标获取存着的Object对象
String str = list.get(i);
System.out.println(str);
}
System.out.println();
//优化后的for循环--foreach结构
//1 2 : 3,其中3是要遍历的数据 1是数据得到类型 2是数据的名字
for(String s : list) {
System.out.println(s);
}
}
}
3 LinkedList
3.1 概述
双向链表,两端效率高。底层就是数组和链表实现的。
3.2 创建对象
LinkedList()
构造一个空列表。
3.3 常用方法
addFirst() addLast()
getFirst() getLast()
removeFirst() removeLast()
void addFirst(E e)
将指定元素插入此列表的开头。
void addLast(E e)
将指定元素添加到此列表的结尾。
E getFirst()
返回此列表的第一个元素。
E getLast()
返回此列表的最后一个元素。
boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。
boolean offerFirst(E e)
在此列表的开头插入指定的元素。
boolean offerLast(E e)
在此列表末尾插入指定的元素。
E peek()
获取但不移除此列表的头(第一个元素)。
E peekFirst()
获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast()
获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
E poll()
获取并移除此列表的头(第一个元素)
E pollFirst()
获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast()
获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pop()
从此列表所表示的堆栈处弹出一个元素。
void push(E e)
将元素推入此列表所表示的堆栈。
E removeFirst()
移除并返回此列表的第一个元素。
E removeLast()
移除并返回此列表的最后一个元素。
3.4 练习1:测试常用方法
双向链表:下标遍历效率低,迭代器遍历效率高
package cn.tedu.arraylist;
import java.util.Iterator;
import java.util.LinkedList;
//测试LinkedList用法
//总结:
//1, 底层的数据结构是数组+链表
//2, 链表结构适合增加或者删除,并不适合查询
//3, 链表结构遍历元素推荐使用迭代器遍历,效率高!!!
public class Test2_LinkedList {
public static void main(String[] args) {
//1,创建对象
LinkedList<String> list = new LinkedList<String>();
//2,常用方法
list.add("钢铁侠");
list.add("美队");
list.add("蜘蛛侠");
list.add("灭霸");
System.out.println(list);
// //特有方法:
// //特点1:首尾元素效率高
list.addFirst("0");//添加
list.addLast("99");
System.out.println(list);
System.out.println(list.getFirst());//获取
System.out.println(list.getLast());
//
System.out.println(list.removeFirst());//移除
System.out.println(list.removeLast());
System.out.println(list);
//遍历元素
//用迭代器遍历 : 效率高!!!
Iterator it = list.iterator();
while(it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
}
//用下标遍历:效率低!!!
for(int i=0 ; i<list.size() ; i++) {
System.out.println(list.get(i));
}
//增强for
for(String s : list) {
System.out.println(s);
}
}
}
4 Set接口
4.1 概述
一个不包含重复元素的 collection。
数据无序(因为set集合没有下标)。
由于集合中的元素不可以重复。常用于给数据去重。
4.2 特点
1、 数据不允许重复
2、 数据无序
3、 HashSet:底层是哈希表
4、 TreeSet:底层是TreeMap,也是红黑树的形式,便于查找数据。
4.3 常用方法
同Collection接口
4.4 练习1:测试常用方法
package cn.tedu.set;
import java.util.HashSet;
import java.util.Set;
//测试Set接口
public class Test3_Set {
public static void main(String[] args) {
//1,创建对象
Set<String> s = new HashSet<>();
//2,常用方法
//同Collection接口,查字典使用
}
}
5 HashSet
5.1 概述
底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。其中,K不许重复。此类允许使用 null 元素。
5.2 练习1:测试常用方法
HashSet()
构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
package cn.tedu.set;
import java.util.HashSet;
import java.util.Iterator;
//测试HashSet使用
//特点1:元素无序 + 元素不可重复
//特点2:底层使用了HashMap来封装数据,默认的容量大小是16
//如果容量不够,会自动扩容,默认的扩容因子是增加0.75的容量
//default initial capacity (16) and load factor (0.75)
public class Test4_HashSet {
public static void main(String[] args) {
//1,创建对象
HashSet<String> set = new HashSet<>();
//2,常用方法
set.add("熊大");
set.add("熊二");
set.add("光头强");
set.add("熊大");
set.add("熊二");
//特点 : 元素无序 + 元素不可重复
System.out.println(set);
//遍历set集合的元素
// Iterator<E> iterator() 返回对此 set 中元素进行迭代的迭代器。
Iterator it = set.iterator();
while( it.hasNext() ) {
Object obj = it.next();
System.out.println(obj);
}
}
}
6 Map接口
6.1 概述
java.util接口 Map<K,V>
类型参数: K - 此映射所维护的键的类型V - 映射值的类型。
也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复.
6.2 特点
1、 可以根据键 提取对应的值 Object value = get(key)
2、 键不允许重复,如果重复值会被覆盖
3、 存放的都是无序数据
4、 初始容量是16,默认的加载因子是0.75
6.3 继承结构
6.4 常用方法
void clear()
从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的 Set 视图。
boolean equals(Object o)
比较指定的对象与此映射是否相等。
V get(Object key)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
int hashCode()
返回此映射的哈希码值。
boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true。
Set<K> keySet()
返回此映射中包含的键的 Set 视图。
V put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。
V remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size()
返回此映射中的键-值映射关系数。
Collection<V> values()
返回此映射中包含的值的 Collection 视图。
6.5 练习1:测试常用方法
package cn.tedu.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
//测试map接口的用法
public class Test5_Map {
public static void main(String[] args) {
//1,创建对象
Map<Integer,String> map = new HashMap<>();
//2,常用方法
//特点1, map中存放的都是有映射关系的数据,key=value
map.put(9528,"如花");
map.put(9527,"唐伯虎");//存数据
//{9527=唐伯虎, 9528=如花}
System.out.println(map);
//特点2, map中元素的key不可以重复,如果发生了重复的key,这时value会被覆盖
//{9527=唐伯虎, 9528=秋香姐}
map.put(9528,"秋香姐");
System.out.println(map);
//特点3, 数据无序
map.put(9000,"渣渣辉");
//{9527=唐伯虎, 9528=秋香姐, 9000=渣渣辉} 与存放顺序不一致
System.out.println(map);
//特点4, 允许存放null键和null值
map.put(null,null);
System.out.println(map);
//常用方法
System.out.println( map.containsKey(9528) );
System.out.println( map.containsValue("渣渣辉") );
System.out.println( map.get(9527) );
System.out.println( map.hashCode() );
System.out.println( map.isEmpty() );
System.out.println( map.remove(9528) );
System.out.println( map.size() );
//遍历map中的元素:map转set
//方式1, keySet() --
//a, 把map中的key取出来存入set -- [null,9527,9000,9528]
Set<Integer> set = map.keySet();
//b, 遍历set集合
Iterator it = set.iterator();
while( it.hasNext() ) {//判断有元素就获取
//c, 分别获取set中存着的每个key值
Integer key = (Integer) it.next();
//d, 拿着key去map中找映射着的value值
String value = map.get(key);
System.out.println(key+"映射的值是:"+value);
}
//遍历map中的元素:map转set
//方式2:Set<Map.Entry<K,V>> entrySet() --
//a, 把map的映射关系形成Entry对象,多个Entry对象放入set集合
Set<Entry<Integer, String>> set2 = map.entrySet();
//b, 遍历set
Iterator<Entry<Integer, String>> it2 = set2.iterator();
while( it2.hasNext() ) {
//c, 获取每个Entry对象
Entry<Integer, String> entry = it2.next();
//d, 分别获取Entry对象封装的K和V
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"对应的值:"+value);
}
}
}
7 HashMap
- HashMap的键要同时重写hashCode()和equals()
hashCode()用来判断确定hash值是否相同
equals()用来判断属性的值是否相同
-- equals()判断数据如果相等,hashCode()必须相同
-- equals()判断数据如果不等,hashCode()尽量不同
7.1 概述
HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。
算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放
当计算的位置有数据时也就是发生hash冲突/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
7.2 练习1:获取HashMap的数据
package cn.tedu.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
//测试map接口的用法
public class Test5_Map {
public static void main(String[] args) {
//1,创建对象
Map<Integer,String> map = new HashMap<>();
//2,常用方法
//特点1, map中存放的都是有映射关系的数据,key=value
map.put(9528,"如花");
map.put(9527,"唐伯虎");//存数据
//{9527=唐伯虎, 9528=如花}
System.out.println(map);
//特点2, map中元素的key不可以重复,如果发生了重复的key,这时value会被覆盖
//{9527=唐伯虎, 9528=秋香姐}
map.put(9528,"秋香姐");
System.out.println(map);
//特点3, 数据无序
map.put(9000,"渣渣辉");
//{9527=唐伯虎, 9528=秋香姐, 9000=渣渣辉} 与存放顺序不一致
System.out.println(map);
//特点4, 允许存放null键和null值
map.put(null,null);
System.out.println(map);
//常用方法
System.out.println( map.containsKey(9528) );
System.out.println( map.containsValue("渣渣辉") );
System.out.println( map.get(9527) );
System.out.println( map.hashCode() );
System.out.println( map.isEmpty() );
System.out.println( map.remove(9528) );
System.out.println( map.size() );
//遍历map中的元素:map转set
//方式1, keySet() --
//a, 把map中的key取出来存入set -- [null,9527,9000,9528]
Set<Integer> set = map.keySet();
//b, 遍历set集合
Iterator it = set.iterator();
while( it.hasNext() ) {//判断有元素就获取
//c, 分别获取set中存着的每个key值
Integer key = (Integer) it.next();
//d, 拿着key去map中找映射着的value值
String value = map.get(key);
System.out.println(key+"映射的值是:"+value);
}
//遍历map中的元素:map转set
//方式2:Set<Map.Entry<K,V>> entrySet() --
//a, 把map的映射关系形成Entry对象,多个Entry对象放入set集合
Set<Entry<Integer, String>> set2 = map.entrySet();
//b, 遍历set
Iterator<Entry<Integer, String>> it2 = set2.iterator();
while( it2.hasNext() ) {
//c, 获取每个Entry对象
Entry<Integer, String> entry = it2.next();
//d, 分别获取Entry对象封装的K和V
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"对应的值:"+value);
}
}
}
7.3 练习2:字符串中的字符统计
接收用户输入的一串字符串,统计出现的每个字符的个数
a=1 b=2 c=3
package cn.tedu.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
//统计字符出现的次数
public class Test6_Count {
public static void main(String[] args) {
//1, 接收键盘输入字符串
String input = new Scanner(System.in).nextLine();
//2, 遍历字符串
//创建map -- {a=3,b=2,c=1}
Map<Character,Integer> map = new HashMap<>();
for(int i = 0 ; i < input.length() ; i++) {
//3, 获取到每个字符
char key = input.charAt(i);
//4, 拿着key去map里查
Integer value = map.get(key);
//5, 如果没有存过(也就是默认值null的话),就存1
if( value == null) {
map.put(key, 1);
}else {
//6, 如果存过,就在原有value基础+1
map.put(key, value+1);
}
}
System.out.println(map);
}
}
8 扩展
8.1 了解栈Stack和队列Queue
8.2 Set存储属性相同的对象
需求:我们假设相同属性的两个人是同一个人
1、按照以前的经验,这种需求只需要重写equals()方法就可以实现。
2、但是我们提供以后,equals()根本就没有执行。问题出现在新增功能。
3、查找新增的源码发现,其实在添加时只是计算对象的hash值。
4、由于每次创建对象时hash值都不一样,所以每次都会当做新对象存起来。
5、所以,现在我们必须保证两个对象的hash值相同,重写hashCode()。
package cn.tedu.map;
import java.util.HashSet;
import java.util.Iterator;
//总结:
//1, 如果使用HashSet对Java中相同属性的对象去重,要求:在类中同时提供重写的equals()和hashCode()
public class Test7 {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<>();
//创建元素
Student s1 = new Student("西门庆",20);
Student s2 = new Student("武大郎",19);
Student s3 = new Student("潘金莲",21);
Student s4 = new Student("小龙女",23);
Student s5 = new Student("武大郎",19);
Student s6 = new Student("潘金莲",21);
//添加时,新元素会和老元素比
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
//默认:添加时查找对象的hash值,没有查到就存起来
//所以必须让hash值一致才可以
set.add(s5);
set.add(s6);
//问题1:属性相同时还是认为是两个对象,存两次???...
System.out.println(set);
}
}
//创建Student类
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
//默认是使用了Object提供的hashCode(),底层会自动运算分配一个hashCode值
//现在的需求:如果属性值相同,产生一个相同的hashCode值,希望根据属性的值产生hashCode值
@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;
}
//默认是使用了Object提供的equals(),是比较两个对象的地址值,如果new了两次返回false
//现在的问题是:虽然new了两次,但是属性值完全一样,还是想要按照是同一个对象处理
//重写equals()的目的就是为了让equals()比较两个对象的属性值是否相同,而不再比较地址值
@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;
}
}