集合
集合只能存储引用类型,若要储数值则创建int对象
int [] arr1={1,2,3};
String [] arr2={"a","b","c"};
sout(Arrays.toString(arr1));
ArrayList<String> list1=new ArrayList<>();
list1.add("a");
sout(list1);
ArrayList<Integer> list2=new ArrayList<>();
list2.add(1);
集合和数组的对比小结
1.数组的长度是不可变的,集合的长度是可变的
2.数组可以存基本数据类型和引用数据类型
集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类
Collection<String> col =new ArrayList<>();
col.add("aaa");
col.add("bbb");
sout(col);
col.removeIf(
(String s)->{return s.length()==3;}
);
col.clear();//清空集合
boolean result1=col.contains("a");
Collection集合的遍历
Iterator:迭代器,集合的专用遍历方式
Iterator<E>iterator():返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引
Iterator中的常用方法
boolean hasNext():判断当前位置是否有元素可以被取出
E next(): 获取当前位置的元素
将迭代器对象移向下一个索引位置
Collection<String> list =new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//1.获得迭代器的对象
//迭代器对象一旦被创建出来,默认指向集合的0索引处
Iterator<String> it=list.iterator();
//利用迭代器里面的方法进行遍历
//当前位置是否有元素可以被取出
sout(it.hasNext());
sout(it.next());
while(it.hasNext())
{
sout(it.next());
}
ArrayList<String> list =new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for(int i=0;i<list.size();i++)
{
String s=list.get(i);
if("b".equals(s))
{
list.remove(i);
i--;
}
}
//相邻 元素无法删除
增强for循环
实现Iterable接口的类才可以使用迭代器和增强for
ArrayList<String> list =new ArrayList<>();
list.add("a");
for(String str:list)
{
sout(str);
}
三种循环的使用场景
如果需要操作索引,使用普通for循环
如果在遍历的过程中需要删除元素,请使用迭代器
如果仅仅想遍历,那么使用增强for
Lis集合概述
1.有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
2.与Set集合不同,列表通常允许重复的元素
Lis集合特点
1.有序:存储和取出的元素顺序一致
2.可重复:存储的元素可以重复
//创建集合对象
List<String> list =new ArrayList<String>();
//添加元素
lis.add("hello");
list.add("world");
//输出集合对象
System.out.println(list);
| 方法名 | 描述 |
| ---------------------------------------- | ------------------- |
| void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
| E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
| E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
| E get(int index) | 返回指定索引处的元素 |
List集合常用实现类
List集合常用子类:ArrayList,LinkedList
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
LinkedList<String> list=new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for(int i=0;i<list.size();i++)
sout(list.get(i));
Iterator<String> it =list.iterator();
while(it.hasNext())
{
sout(it.next());
}
for(String s:list)
{
sout(s);
}
LinkedList集合的特有功能
Collection
Set集合概述和特点
1.可以去重复
2.存取顺序不一致
3.没有带索引的方法,所以不能使用for循环遍历,也不能通过索引来获取,删除Set集合里面的元素
public class Student implements Comparable<Student>
{
private String name;
private int age;
public Student()
{
}
public Student(String name,int age)
{
this.name=name;
this.age=age;
}
...............
public int compareTo(Studnet 0)
{
//按照对象的年龄进行排序
int result=this.age-o.age;
return result
}}
自然排序简单原理图
public int compareTo(Student 0)
{
//按照对象的年龄进行排序
//主要判断条件
int result=this.age-o.age;
//次要判断条件
result=result==0?this.name.compareTo(o.getName()):result;
return result;
}
public static void main(String [] args)
{
TreeSet<Teacher> ts=new TreeSet<>(new Comparator<Teacher>(){
@override
public int compare(Teacher 01,Teacher 02)
{ //01表示现在要存入的那个元素
//02表示已经存入到集合中的元素
int result=01.getAge()-o2.getAge();
result=result==0?01.getName().compareTo(02.getName()):result;
return result}}
);
}
Set
两种比较方式小结
1.自然排序:自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序
2.比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序
3.在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,使用比较器排序
两种方式中,关于返回值的规则:
1.如果返回值为负数,表示当前存入的元素是较小值,存左边
2.如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
3.如果返回值为正数,表示当前存入的元素是较大值,存右边
TreeSet集合概述和特点
TreeSet集合特点
1.不包含重复元素的集合
2.没有带索引的方法
3.可以将元素按照规则进行排序
自然排序Comparable的使用
使用空参构造创建TreeSet集合
自定义的Student类实现Comparable接口
重写里面的compareTo方法
public class Student implements Comparable<Student>
{
....................
@Override
public int compareTo(Student o)
{
int result=this.age-o.age;
return result;
}
}
例子:
public int compareTo(Student o)
{
//按照对象的年龄进行排序
//主要判断条件
int result=this.age-o.age;
//次要判断条件
result=result==0?this.name.compareTo(o.getName()):result;
return result;
}
public static void main(String[] args)
{
TreeSet<Teacher> ts=new TreeSet<>(new Comparator<Teacher>(){
@Override
public int compare(Teacher o1,Teacher o2)
{ //o1表示现在要存入的那个元素
//o2表示已经存入到集合中的元素
int result=o1.getAge()-o2.getAge();
result=result==0? o1.getName().compareTo(o2.getName):result;
return result;
}
});
}
两种比较方式小结
自然排序:自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序
比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,使用比较器排序
案例
TreeSet<String> ts=new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1,String o2)
{
int result=o1.length()-o2.length();
result=result==0?o1.compareTo(o2):result;
return result;
}});
ts.add("c");
ts.add("ab");
ts.add("df");
//方法二:
TreeSet<String> ts=new TreeSet<>(
(String o1,String o2)->{
int result =o1.length()-o2.length();
result=result==0?o1.compareTo(o2):result;
return result;
});
泛型概述
Collection c=new ArrayList();
c.add("hello");
c.add("world");
//集合遍历
Iterator it=c.iterator();
while(it.hasNext())
{
Object obj=it.next();
sout(obj);
}
泛型的好处:
把运行时间的问题提前到了编译期间
避免了强制类型转换
Collection<String> c=new ArrayList<String>();
c.add("hello");
Iterator<String> it=c.iterator();
while(it.hasNext()){
String s=it.next();
sout(s);
}
泛型类
泛型类的定义格式:
格式:修饰符 class 类名<类型>{ }
范例: public class Generic<T>{ }
此处T可以随便写为任意标识,常见的如T,E,K,V等形式的参数常用于表示泛型
public class Generic<T>{
private T t;
public T getT(){
return t;
}
public void setT(T t)
{
this.t=t;
}
}
psvm
{
Generic<String> g1=new Generic<String>();
g1.setT("王祖蓝");
}
泛型方法
泛型方法的定义格式:
格式:修饰符<类型>返回值类型方法名(类型 变量名){ }
范例:public<T> void show(T t){ }
public class Generic {
public <T> void show(T t)
{
sout(t);
}
}
泛型接口
泛型接口的定义格式
格式:修饰符interface 接口名 <类型>{ }
泛型:public interface Generic<T>{ }
public interface Generic<T>{
void show(T t);
}
接口实现类:
public class GenericImpl<T> implements Generic<T>{
@Override
public void show(T t)
{
sout(t);
}}
泛型接口的使用方式:
实现类也不给泛型
实现类确定具体的数据类型
public class GenericityInterface{
public static void main(String[] args)
{
GenericityImpl<String> genericity=new GnericityImpl<>();
genericity.method("哈哈哈哈哈");
}
}
interface Genricity<E>{
public abstract void method(E e);
}
class GenericityImpl<E> implements Genericity<E>
{
@Override
public void method(E e)
{
sout(e);
}
}
类型通配符
//类型通配符:<?>
List<?> list1=new ArrayList<Object>();
List<?> list2=new ArrayList<Number>();
List<?> list3=new ArrayList<Integer>();
//类型通配符上限:<? extends 类型>
List<? extends Number> list5=new ArrayList<Number>();
List<? extends Number> list6=new ArrayList<Integer>();
//类型通配符下限:<? super 类型>
List<? super Number> list7=new ArrayList<Object>();
List<? super Number> list8=new ArrayList<Number>();
//表示传递进来集合的类型,可以是Number类型,也可以是Number所有的子类类型
private static void method1(ArrayList<? extends Number>list){}
//表示传递进来集合的类型,可以是Number类型,也可以是Number让所有的父类类型
private static void method2(ArrayList<? super Number>list){}
private static void printList(ArrayList<?> list){}
树和二叉树
Set集合
二叉查找数
红黑树
红黑规则
HashSet集合概述和特点
底层数据结构是哈希表
不能保证存储和取出的顺序完全一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以元素唯一
HashSet<String> hs =new HashSet<>();
hs.add("hello");
hs.add("world");
Iterator<String> it =hs.iterator();
while(it.hasNext())
{
sout(it.next());
}
for(String s:hs)
{
sout(s);
}
Map集合
Map集合的获取功能
public static void main(String[] args)
{
HashMap<String,ArrayList<String>>hm=new HashMap<String,ArrayList<String>>();
ArrayList<String> arry1=new ArrayList<String>();
arry1.add("诸葛亮");
arry1.add("赵云");
hm.put("三国演义",arry1);
ArrayList<String> arry2=new ArrayList<String>();
arry2.add("猪八戒");
arry2.add("孙悟空");
hm.put("西游记",arry2);
Set<String> keyet=hm.keySet();
for(String s1:keyset)
{
ArrayList<String> value=hm.get(s1);
for(String s:value)
sout(s);
}}
public static void main(String[] args)
{
HashMap<String,String>hm1=new HashMap<String,String>();
ArrayList<HashMap<String,String>> arry=new ArrayList<HashMap<String,String>>();
hm1.put("孙策","大桥");
arry.add(hm1);
HashMap<String,String>hm2=new HashMap<String,String>();
hm2.put("郭靖","黄蓉");
arry.add(hm2);
for(HashMap<String,String> hm:arry)
{
Set<String> keySet=hm.keySet();
for(String key:keySet)
{
String value=hm.get(key);
}}}
案例统计字符串每个字符出现的次数
public class HashMapDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
HashMap<Character, Integer> hm = new HashMap<Character, Integer>();
for (int i = 0; i < line.length(); i++) {
char key = line.charAt(i);
Integer value = hm.get(key);
if (value == null) {
hm.put(key, 1);
} else {
value++;
hm.put(key, value);
}
}
//遍历HashMap集合,得到健和值,按照要求进行拼接
StringBuilder sb = new StringBuilder();
Set<Character> keyset = hm.keySet();
for (Character key1 : keyset) {
Integer value1=hm.get(key1);
sb.append(key1).append("(").append(value1).append(")");
}
String result=sb.toString();
System.out.println(result);
}
}
TreeMap和Hashmap用法一样,只是TreeMap对键进行了排序
Collections概述和使用
Collections类的概述
是针对集合操作的工具类
Collections类的常用方法
List<Integer> list=new ArrayList<Integer>();
list.add(30);
list.add(10);
list.add(20);
list.add(40);
Collections.sort(list);
Collections.reverse(list);
Collections.shuffle(list);
sout(list);
ArrayList<String> list1=new ArrayList<String>(List.of("张三","李四","王五"));
ArrayList<String> list2=new ArrayList<>();
for(String s:list)
{
if(s.startsWith("张"))
{
list2.add(s);
}
}
ArrayList<String> list3=new ArrayList<>();
for(String s:list2)
{
if(s.length()==3)
{
list3.add(s);
}
}
for(String s:list3)
{
sout(s);
}
Stream流
ArrayList<String> list1=new ArrayList<>(List.of("张三丰","张无忌","张弛"));
ArrayList<String> list2=new ArrayList<>();
for(String s:list1)
{
if(s.startsWith("张"))
{
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,在添加到list3中
ArrayList<String> list3=new ArrayList<>();
for(String s:list2)
{
if(s.length()==3)
{
list3.add(s);
}
}
//Stream 流
list1.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s->sout(s));
Stream流的三类方法
获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作
中间方法
流水线上的操作
一次操作完毕之后,还可以继续进行其他操作
终结方法
一个Stream流只能有一个终结方法
是流水线上的最后一个操作
Stream流的获取方法
体验Stream流
//单列集合
ArrayList<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
Stram<String> stream=list.stream();
stream.forEach(s->sout(s));
list.stream().forEach(s->sout(s));
//双列集合
HashMap<String,Integer> hm=new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("zhaoliu",26);
//双列集合不能直接获取Stream流
//keySet
//先获取到所有的键
//再把这个Set集合中所有的键放到Stream流中
hm.KeySet().stream().forEach(s->sout(s));
//双列集合
//entrySet
//先获取到所有的键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s->sout(s));
数组(流)
int [] arr={1,2,3,4,5};
Arrays.stream(arr).forEach(s->sout(s));
Stream.of(1,2,3,4,5).forEach(s->sout);
Stream流的常见中间操作方法
list.stream().filter(
new Predicate<String>()
{ @Override
public boolean test(String s){
boolean result =s.startsWith("张");
return result;
} }).forEach(s->sout(s));
//因为Predicate 接口中只有一个抽象方法test
//所以我们可以使用lambda表达式来简化
list.stream().filter(
(String s)->{
boolean result=s.startsWith("张");
return result;
}).forEach(s->sout(s));
list.stream().filter(s->s.startsWith("张")).forEach(s->sout(s));
Stream流的常见中间操作方法
list.stream().limit(2).forEach(s->sout(s));
list.stream().skip(2).forEach(s->sout(s));
Stream<String> stream1=list.stream();
Stream<String> stream2=list2.stream();
Stream<String> stream3=Stream.concat(stream1,stream2);
stream3.forEach(s->sout(s));
list.stream().distinct().forEach(s->sout(s));
Stream流的常见终结操作方法
list.stream().forEach(
new Consumer<String>()
{@Override
public void accept(String s)
{
sout(s);
} });
list.stream().forEach(
(String s)->{
sout(s);
});
list.stream().forEach(s->sout(s));
Stream流的收集操作
需求:过滤元素并遍历集合
定义一个集合,并添加一些整数1,2,3,4,5,6,7
将集合中的奇数删除,只保留偶数
遍历集合得到2,4,6,8,10
ArrayList<Integer> list =new ArrayList<>();
for(int i=1;i<=10;i++)
{
list.add(i);
}
list.stream().filter(
(Integer i)->{
return i%2==0;
})
list.stream().filter(number->number%2==0).forEach(number->sout(number));
注意在:Stream流中 无法直接修改集合,数组等数据源中的数据
List<Integer> list=list1.stream().filter(number->number%2==0).collect(Collectors.toList());
Set<Integer> set=list1.stream().filter(number->number%2==0).collect(Collectors.toSet());
ArrayList<String> list=new ArrayList<>();
list.add("zhangsan,23");
list.add("lisi,25");
list.add("wangwu,18");
list.stream().filter(
(String s)->{
String [] split=s.split(",");
int age=Integer.parseInt(split[1]);
return age>=24;}).forEach(s->sout(s));
Map<String,Integer> map=list.stream().filter(
s->{ String [] split=s.split(",");
int age=Integer.parseInt(split[1]);
return age>=24;}).collect(Collectors.toMap((String s)->{return s.split(",")[0];},
(String s)->{
return Integer.parseInt(s.split(",")[1]);
}));