Collection
Collection集合概述:是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素。
JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现。
package MyProject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class Demo{
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
c.add("hello");
c.add("java");
System.out.println(c);
输出:[hello, java]
}
}
Collection集合常用方法
package MyProject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class Demo{
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
c.add("hello");
c.add("java");
c.add("world");
c.remove("java");//删除指定元素
System.out.println(c.add("world"));
System.out.println(c);
//输出:true
//[hello, world, world]
//说明可以存入重复的元素,add返回的永远是true。
System.out.println(c.remove("javaaaa"));
//输出false,集合中没有这个元素
//c.clear(); 清空集合中所有元素
System.out.println(c.contains("javaaaa"));
//输出false,判断集合中是否存在该元素
System.out.println(c.isEmpty());
//输出false,判断集合是否为空
System.out.println(c.size());
//输出集合中元素个数
}
}
Collection集合遍历
Iterator:迭代器,集合的专用遍历方式。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class Demo{
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
c.add("hello");
c.add("java");
c.add("world");
Iterator<String> it=c.iterator();
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
}
}
输出:
若末尾再加一行输出it.next();
则报错NoSuchElementException:表示请求的元素不存在。
为了防止报错:it.hasNext()判断后面是否还有元素
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
c.add("hello");
c.add("java");
c.add("world");
Iterator<String> it=c.iterator();
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
//输出三行元素
利用循环遍历:
Iterator<String> it=c.iterator();
while (it.hasNext())
{
String s=it.next();
System.out.println(s);
}
案例:
//学生类
package MyProject;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
public String getName(){
return name;
}
}
//测试
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class Demo{
public static void main(String[] args) {
Collection<Student> c=new ArrayList<Student>();
Student s1=new Student("aa");
Student s2=new Student("bb");
Student s3=new Student("cc");
c.add(s1);
c.add(s2);
c.add(s3);
Iterator<Student> it=c.iterator();
while (it.hasNext())
{
Student s=it.next();
System.out.println(s.getName());
}
}
}
输出:
List
List集合概述: 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素并搜索列表中的元素。
与Set集合不同,列表通常允许重复的元素。
List集合特点:
有序:存储和取出的元素顺序一致。
可重复:存储的元素可以重复。前面那个Collection也可以有重复元素。
import java.util.ArrayList;
import java.util.List;
public class Demo{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("world");
System.out.println(list);
//输出:[hello, world, world]
}
}
遍历:
Iterator<String> it=list.iterator();
while (it.hasNext())
{
String s=it.next();
System.out.println(s);
}
List集合特有方法
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("world");
list.add("nihao");
list.add(2,"bu");//指定位置插入元素
list.remove(1);//删除下标为1的元素,返回被删除的元素
list.set(2,"hhhh");//修改下标为2的元素为hhhh
System.out.println(list.get(2));//返回下标为2的元素内容
还可以这样遍历:
for(int i=0;i<list.size();i++)
System.out.println(list.get(i));
并发修改异常
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("nihao");
Iterator<String> it=list.iterator();
/*下面的方法报错
while (it.hasNext())
{
String s=it.next();
if(s.equals("world")){
list.add("aaaa");
}
}
*/
for(int i=0;i<list.size();i++)
{
String s=list.get(i);
if(s.equals("world")){
list.add("aaaa");
}
System.out.println(list.get(i));
}
}
}
输出:
ListIterator:列表迭代器
通过List集合的ListIterator()方法得到,所以说它是List集合特有的迭代器。
遍历:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Demo{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("nihao");
ListIterator<String> it=list.listIterator();
//正向遍历
while (it.hasNext())
{
String s=it.next();
System.out.println(s);
}
//反向遍历 少用
while (it.hasPrevious())
{
String s=it.previous();
System.out.println(s);
}
}
}
迭代器中的add
之前是集合中的add,而这里是ListIterator中的add
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Demo{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("nihao");
ListIterator<String> it=list.listIterator();
//正向遍历
while (it.hasNext())
{
String s=it.next();
if(s.equals("hello")){
it.add("aaa");
}
}
System.out.println(list);
}
}
输出:
这里不会报错,说明可以用ListIterator中的add在迭代器遍历时添加元素。
增强for循环
简化数组和Collection集合的遍历。
这里类似于c++中的for(auto 变量名:数组名)
例子:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Demo{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("nihao");
for(String s:list){
System.out.println(s);
}
}
}
List集合子类特点
List集合常用子类:
ArrayList(底层数据结构是数组,查询快,增删慢)
LintkedList(底层数据结构是链表,查询慢,增删快)
ArrayList三种遍历方式:
package MyProject;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo{
public static void main(String[] args) {
ArrayList<String> arr=new ArrayList<String>();
arr.add("hh");
arr.add("Aa");
arr.add("ddd");
for(String s:arr){
System.out.println(s);
}
for(int i=0;i<arr.size();i++){
System.out.println(arr.get(i));
}
Iterator<String> it=arr.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println(s);
}
}
}
LinkedList三种遍历方式:(和上面一样)
package MyProject;
import java.util.Iterator;
import java.util.LinkedList;
public class Demo{
public static void main(String[] args) {
LinkedList<String> arr=new LinkedList<String>();
arr.add("hh");
arr.add("Aa");
arr.add("ddd");
for(String s:arr){
System.out.println(s);
}
for(int i=0;i<arr.size();i++){
System.out.println(arr.get(i));
}
Iterator<String> it=arr.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println(s);
}
}
}
LinkedList集合的特有功能
Set集合
特点:不包含重复元素,没有带索引的方法,索引不能使用普通for循环遍历。
Set是个接口,不能直接实例化。
HashSet:对集合的迭代顺序不作任何保证。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
Set<String> set=new HashSet<String>();
set.add("hh");
set.add("Aa");
set.add("ddd");
set.add("ddd");//不含有重复元素
for(String s:set){
System.out.println(s);
}
Iterator<String> it=set.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println(s);
}
}
}
输出:
哈希值
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。
HashSet集合概述和特点
常见数据结构之哈希表
//学生类
package MyProject;
import java.util.Objects;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
public String getName(){
return name;
}
//下面的内容打出equals自动生成,是为了让哈希表不存入重复的元素
//如果没有下面的元素,那么哈希表会存入两个aaa
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
//测试
import java.util.HashSet;
public class Demo{
public static void main(String[] args) {
HashSet<Student> hs=new HashSet<Student>();
Student s1=new Student("aaa");
Student s2=new Student("bbb");
Student s3=new Student("ccc");
Student s4=new Student("aaa");
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
for(Student s:hs)
{
System.out.println(s.getName());
}
}
}
输出:
LinkedHashSet集合概述和特点
import java.util.LinkedHashSet;
public class Demo{
public static void main(String[] args) {
LinkedHashSet<String> hs=new LinkedHashSet<String>();
hs.add("aaa");
hs.add("bbb");
hs.add("ccc");
hs.add("ccc");
for(String s:hs)
{
System.out.println(s);
}
}
}
输出:
TreeSet集合概述和特点
import java.util.TreeSet;
public class Demo{
public static void main(String[] args) {
TreeSet<Integer> ts=new TreeSet<Integer>();
//这里不是int而是Integer的原因:
//所有基本类型存储的时候要用其对应的包装类型
ts.add(10);
ts.add(100);
ts.add(66);
ts.add(66);
for(Integer i:ts)
{
System.out.println(i);
}
}
}
输出:自动排序且不含重复元素
自然排序Comparable的使用
//学生类
public class Student implements Comparable<Student>{
//实现Comparable接口
String name;
int age;
public Student(String name,int age) {
this.name = name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public int compareTo(Student s){
//return 0;s1与s2、s3..元素一样,只添加s1,只输出s1
//return 1;默认s1比s2小,s2比s3小...从小到大输出
//return -1;默认s2比s1小,s3比s2小...从大到小输出
int num=this.age-s.age;
//当num=0时,下一个元素被看作重复元素,不会存入
return num;
}
}
//测试
import java.util.TreeSet;
public class Demo{
public static void main(String[] args) {
TreeSet<Student> ts=new TreeSet<Student>();
Student s1=new Student("xishi",12);
Student s2=new Student("yang",32);
Student s3=new Student("yanl",25);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for(Student s:ts)
{
System.out.println(s.getName()+" "+s.getAge());
}
}
}
输出:
由于年龄可能一样,这样写的话两个年龄一样的个体就不能同时存入,而且还有当年龄一样比较名字的需求。
改进:
//学生类
public class Student implements Comparable<Student>{
String name;
int age;
public Student(String name,int age) {
this.name = name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public int compareTo(Student s){
int num=this.age-s.age;
int num1=num==0?this.name.compareTo(s.name):num;
return num1;
}
}
//测试
import java.util.TreeSet;
public class Demo{
public static void main(String[] args) {
TreeSet<Student> ts=new TreeSet<Student>();
Student s1=new Student("xishi",12);
Student s2=new Student("yang",32);
Student s3=new Student("yanl",25);
Student s4=new Student("aaa",12);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for(Student s:ts)
{
System.out.println(s.getName()+" "+s.getAge());
}
}
}
输出:
当姓名年龄都相同时,重复的元素不会存入。
比较器排序Comparable的使用
//学生类
public class Student{
String name;
int age;
public Student(String name,int age) {
this.name = name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
//测试
import java.util.Comparator;
import java.util.TreeSet;
public class Demo{
public static void main(String[] args) {
TreeSet<Student> ts=new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//this.age-s.age
//s1-s2
int num1=s1.getAge()-s2.getAge();
int num2=num1==0?s1.getName().compareTo(s2.getName()):num1;
return num2;
}
});
Student s1=new Student("xishi",12);
Student s2=new Student("yang",32);
Student s3=new Student("yanl",25);
Student s4=new Student("aaa",12);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for(Student s:ts)
{
System.out.println(s.getName()+" "+s.getAge());
}
}
}
输出:
自然排序和比较器排序规则定义和效果一样,只不过自然排序是在学生类中实现Comparable,而比较器排序是在TreeSet有参构造中实现。
案例
随机数:用random实现
不重复:用Set集合
思路:
利用HashSet实现:
import java.util.*;
public class Demo{
public static void main(String[] args) {
Set<Integer> set=new HashSet<Integer>();
Random r=new Random();
while (set.size()<10)
{
int num=r.nextInt(20)+1;
set.add(num);//重复的元素不会添加进去
}
for(Integer i:set)
{
System.out.println(i);
}
}
}
输出:10个20以内的随机数
用TreeSet实现:
import java.util.*;
public class Demo{
public static void main(String[] args) {
Set<Integer> set=new TreeSet<Integer>();
Random r=new Random();
while (set.size()<10)
{
int num=r.nextInt(20)+1;
set.add(num);//重复的元素不会添加进去
}
for(Integer i:set)
{
System.out.println(i);
}
}
}
输出:10个20以内的随机数从小到大输出。
泛型
```java
import java.util.*;
public class Demo{
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
//这里的<String>就用到了泛型,就是规定了存入的数据类型
c.add("hello");
c.add("ni");
Iterator<String> it=c.iterator();
while (it.hasNext())
{
String s=it.next();
System.out.println(s);
}
}
}
泛型的好处:
将运行时期的问题提前到了编译期间。
避免了强制类型转换。
泛型类
//泛型类
public class Student<T>{
private T t;
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
}
//测试
public class Demo{
public static void main(String[] args) {
Student<String> s1=new Student<String>();
s1.setT("aaa");
Student<Integer> s2=new Student<Integer>();
s2.setT(12);
System.out.println(s1.getT());
System.out.println(s2.getT());
//输出:aaa
// 12
}
}
泛型方法
//泛型类+泛型方法
public class Student<T>{
private T t;
public void show(T t){
System.out.println(t);
}
}
//测试
public class Demo{
public static void main(String[] args) {
Student<String> s1=new Student<String>();
s1.show("Saaa");
//输出:Saaa
}
}
但每次创建对象的时候都要明确数据类型,有些麻烦。所以可以改进为调方法的时候再明确数据类型。这里就要用到泛型方法。
//泛型方法
public class Student{
public <T> void show(T t){
System.out.println(t);
}
}
//测试
public class Demo{
public static void main(String[] args) {
Student s1=new Student();
s1.show("Saaa");
s1.show(30);
s1.show(true);
//输出 Saaa
// 30
// true
}
}
泛型接口
//接口
package MyProject;
public interface Inter<T> {
void show(T t);
}
//接口实现类
package MyProject;
public class Student<T> implements Inter<T>{
public void show(T t){
System.out.println(t);
}
}
//测试
public class Demo{
public static void main(String[] args) {
Student<String> s1=new Student<String>();
s1.show("aaa");
Student<Integer> s2=new Student<Integer>();
s2.show(12);
}
}
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符。
import java.util.ArrayList;
import java.util.List;
public class Demo{
public static void main(String[] args) {
//类型统配符 <?>
List<?> l1=new ArrayList<Object>();
List<?> l2=new ArrayList<Number>();
List<?> l3=new ArrayList<Integer>();
//类型通配符上限<? extends 类型>
List<? extends Number> l4=new ArrayList<Number>();
List<? extends Number> l5=new ArrayList<Integer>();
List<? extends Number> l=new ArrayList<Object>();//报错
//类型通配符下限<? extends 类型>
List<? super Number> l6=new ArrayList<Number>();
List<? super Number> l7=new ArrayList<Object>();
List<? super Number> l8=new ArrayList<Integer>();//报错
}
}
Object>Number>Integer
可变参数
public class Demo{
public static void main(String[] args) {
System.out.println(sum(10,20,30));
System.out.println(sum(20,30,40,50));
}
public static int sum(int...a){
int sum=0;
for(int i:a)
sum+=i;
//这里的a相当于是数组
return sum;
}
}
输出:60 140
满足了需要不同个数的数字相加的结果的需求。否则要写多个函数,不同个数的形参。
当需要传入多个形参的时候,可变参数放后面,不然会报错。
例:
改正:
可变参数的使用
//public static <T> list<T> asList(T... a):返回由指定数组支持的固定大小的列表
List<String> list= Arrays.asList("hello","world","java");
/*不可以增删
List.add("aava");
List.remove("java");
*/
//可以修改指定位置元素内容
list.set(1,"aaa");
List.of()方法和Set.of()方法都不能增删改。
Map集合
import java.util.HashMap;
import java.util.Map;
public class Demo{
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("aaa","111");
map.put("bbb","222");
map.put("aaa","3333");
System.out.println(map);
//输出:{aaa=3333, bbb=222}
//当key值重复时,元素内容会被替换掉
}
}
Map集合的基本功能
remove返回的值是键值对应的元素值,若不存在该键值,则返回null。
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("aaa","111");
map.put("bbb","222");
//V get(Object key):根据键获取值
System.out.println(map.get("aaa"));
System.out.println(map.get("sss"));//没有该键,也就没有对应值,输出null
//Set<K> keySet():获取所有键的集合
Set<String> keySet=map.keySet();
for(String key:keySet)
{
System.out.println(key);
}
//Collection<V> value():获取所有值的集合
Collection<String> values=map.values();
for(String value:values)
{
System.out.println(value);
}
}
}
输出:
Map集合的遍历方式(一)
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();//创建集合对象
map.put("aaa","1111");
map.put("bbb","564");
map.put("ccc","564");
map.put("ddd","46813");
Set<String> keys=map.keySet();//获取key值集合
for(String key:keys)//遍历key值
{
System.out.println(map.get(key));//通过key值get到value值
}
}
}
输出:
Map集合的遍历方式(二)
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();//创建集合对象
map.put("aaa","1111");
map.put("bbb","564");
map.put("ccc","564");
map.put("ddd","46813");
//获取所有键值对对象的集合
Set<Map.Entry<String,String>> entrySet=map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for(Map.Entry<String,String> me : entrySet){
//根据键值对对象获取键和值
String key=me.getKey();
String value=me.getValue();
System.out.println(key+" "+value);
}
}
}
输出:
方式一:键找值
public class Demo{
public static void main(String[] args) {
Map<String,Student> map=new HashMap<String,Student>();
Student s1=new Student("aaa",12);
Student s2=new Student("bb",56);
Student s3=new Student("sd",59);
map.put("aaa",s1);
map.put("bbb",s2);
map.put("ccc",s3);
//键找值
Set<String> keySet=map.keySet();
for(String key:keySet)
{
Student s=map.get(key);
System.out.println(s.getName()+" "+s.getAge());
}
}
}
输出:
方式二:键值对象找键和值
public class Demo{
public static void main(String[] args) {
Map<String,Student> map=new HashMap<String,Student>();
Student s1=new Student("aaa",12);
Student s2=new Student("bb",56);
Student s3=new Student("sd",59);
map.put("aaa",s1);
map.put("bbb",s2);
map.put("ccc",s3);
Set<Map.Entry<String,Student>> entrySet=map.entrySet();
for(Map.Entry<String,Student> me:entrySet)
{
String key=me.getKey();
Student s=me.getValue();
System.out.println(key+" "+s.getName()+" "+s.getAge());
}
}
}
输出:
//学生类
import java.util.Objects;
public class Student{
String name;
int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
//测试
public class Demo{
public static void main(String[] args) {
Map<Student,String> map=new HashMap<Student,String>();
Student s1=new Student("aaa",12);
Student s2=new Student("bb",56);
Student s3=new Student("sd",59);
Student s4=new Student("sd",59);
map.put(s1,"西安");
map.put(s2,"北京");
map.put(s3,"长城");
map.put(s4,"故宫");
Set<Student> keySet=map.keySet();
for(Student key:keySet)
{
String value=map.get(key);
System.out.println(key.getName()+" "+key.getAge()+" "+value);
}
}
}
输出:
ArrayList集合存储HashMap元素并遍历
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
ArrayList<HashMap<String,String>> a=new ArrayList<HashMap<String,String>>();
HashMap<String,String> h1=new HashMap<String, String>();
h1.put("aaa","111");
h1.put("bbb","222");
a.add(h1);
HashMap<String,String> h2=new HashMap<String, String>();
h2.put("ccc","333");
h2.put("ddd","444");
a.add(h2);
for(HashMap<String,String> hm:a)
{
Set<String> keySet=hm.keySet();
for(String key:keySet){
String value=hm.get(key);
System.out.println(key+" "+value);
}
}
}
}
HashMap集合存储ArrayList元素并遍历
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class Demo{
public static void main(String[] args) {
HashMap<String,ArrayList<String>> h=new HashMap<String, ArrayList<String>>();
ArrayList<String> a1=new ArrayList<String>();
a1.add("aaa");
a1.add("cccc");
a1.add("vvv");
h.put("1",a1);
ArrayList<String> a2=new ArrayList<String>();
a2.add("sss");
a2.add("dddd");
a2.add("hhrt");
h.put("2",a2);
Set<String> keySet=h.keySet();
for(String key:keySet){
ArrayList<String> value=h.get(key);
for(String s:value){
System.out.println(key+" "+s);
}
}
}
}