集合
1.1集合类的特点
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变。
1.2集合类体系结构
1.3Collection集合概述
- 是单例集合的顶层接口,它表示一组对象,这些对象也被称为Collection的元素
- JDK不提供此接口的直接实现,它提供更具体的子接口实现
- 以多态的方式创建Collection对象
1.4Collection集合常用方法
boolean add(E e); 添加元素
boolean remove(Object o); 从集合中移除指定元素
void clear();清空集合的元素
boolean contains(Object o);判读集合中是否存在指定的元素
boolean isEmpty();判断集合是否为空
int size(); 集合的长度,也就是集合中元素的个数
1.5Collection集合的遍历
Iterator<E> iterator(); 返回此集合中元素的迭代器,通过集合的iterator()方法得到
E next(); 返回迭代的下一个元素
boolean hasNext(); 如果迭代具有更多元素,则返回true
public class CollectionDemo02 {
public static void main(String[] args) {
Collection<String>collection = new ArrayList<>();
collection.add("12");
collection.add("34");
collection.add("156");
collection.add("177");
Iterator<String>iterator = collection.iterator();
while (iterator.hasNext())
{
String s = iterator.next();
System.out.println("s = " + s);
}
}
}
2.1List集合概述和特点
List集合概述
- 有序集合(也称为序列),用户可以控制每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常运行重复的元素
2.2List集合的方法
void add(int index,E element); 在此集合中的指定位置插入指定的元素
E element(int index); 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
public class CollectionDemo04 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("Java");
list.add("Python");
System.out.println("list = " + list);
list.add(1,"sb")
System.out.println("list = " + list);
list.remove(1);
System.out.println("list = " + list);
System.out.println(list.set(1, "love"))
System.out.println("list = " + list);
System.out.println(list.get(3));
}
}
2.3List集合的遍历
Iterator<Student>iterator = list.iterator();
while (iterator.hasNext()){
Student s = iterator.next();
System.out.println(s.getName()+","+s.getAge());
}
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName()+","+s.getAge());
}
2.4并发修改异常
ConcurrentModificationException
产生原因: 迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值与实际修改值不一致。
解决方案:用for循环遍历,然后用集合对象做对应的操作即可
//错误代码
Iterator<String>iterator = list.iterator();
while (iterator.hasNext())
{
if (iterator.next().equals("wolrd")){
list.add("23");
}
}
//修改后:
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.equals("wolrd")){
list.add("23");
}
}
2.5ListIterator
ListIterator: 列表迭代器
- 通过List集合的ListIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListIterator中的常用方法
E next(); 返回迭代中的下一个元素
boolean hasNext(); 如果迭代具有更多元素,则返回true
E previous(); 返回列表中的上一个元素
boolean hasPrevious(); 如果此列表迭代器在相反遍历列表时具有更多元素,则返回true
void add(E e): 将指定的元素插入列表 -------------> 可用来解决并发修改异常
ListIterator<String>listIterator = list.listIterator();
while (listIterator.hasNext())
{
if (listIterator.next().equals("hello"))
listIterator.add("are");
}
System.out.println(list);
2.6LinkedList的特有方法
public void addFirst(E e); 在该列表开头插入指定的元素
public void addLast(E e); 将指定的元素追加到此列表的末尾
public E getFirst(); 返回此列表的第一个元素
public E getLast(); 返回此列表的最后一个元素
public E removeFirst(); 从此列表删除并返回第一个元素
public E removeLast(); 从此列表中删除并返回最后一个元素
3.1Set集合的特点
不包含重复元素的集合
没有带索引的方法,所以不能使用普通for循环遍历
HashSet: 对集合的迭代顺序不作任何保证
public class SetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("hello");
set.add("world");
set.add("javaee");
//1.增强for循环遍历
for (String s : set) {
System.out.println("s = " + s);
}
//2.迭代器遍历
Iterator<String>iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
哈希值
哈希值: 时jdk根据对象的地址或者字符串或者数字算出来的int类型的数值
Obejct类中有一个方法可以获取对象的哈希值
public int hashCode();
对象哈希值特点:
- 同一个对象多次调用hashCode()方法返回的哈希值相同
- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以让不同对象的哈希值相同
3.2HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
public class HashSet01 {
public static void main(String[] args) {
HashSet<String>hashSet = new HashSet<>();
hashSet.add("hello");
hashSet.add("hello");
hashSet.add("world");
hashSet.add("javaee");
System.out.println("hashSet = " + hashSet); //hashSet = [world, hello, javaee]
}
}
3.3HashSet集合的使用
public class HashSet02 {
public static void main(String[] args) {
HashSet<Student>hashSet = new HashSet<>();
Student student1 = new Student("张三",18);
Student student2 = new Student("李四",19);
Student student3 = new Student("李四",19);
Student student4 = new Student("王五",30);
hashSet.add(student1);
hashSet.add(student2);
hashSet.add(student3);
hashSet.add(student4);
for (Student student : hashSet) {
System.out.println("student = " + student);
}
}
}
为保证Student元素不重复,需重写hashCode和equals方法
4.1LinkedHashSet集合的特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("hello");
linkedHashSet.add("world");
linkedHashSet.add("javaee");
linkedHashSet.add("hello");
for (String s : linkedHashSet) {
System.out.println("s = " + s);
}
/*
s = hello
s = world
s = javaee
*/
}
}
5.1TreeSet集合概述
-
元素有序,排序顺序取决于构造方法
TreeSet():根据其元素的自然顺序进行排序
TreeSet(Comparator comparator): 根据指定的比较器进行排序
-
没有带索引的方法,所以不能使用普通的for循环遍历
-
不包含重复元素的集合
public class TreeSet01 {
public static void main(String[] args) {
TreeSet<Integer>treeSet = new TreeSet<Integer>();
treeSet.add(12);
treeSet.add(123);
treeSet.add(34);
treeSet.add(54);
treeSet.add(13);
for (Integer integer : treeSet) {
System.out.println("integer = " + integer);
}
}
}
5.2自然排序Comparable的使用
public class Student implements Comparable<Student> {
private Integer age;
private String name;
@Override
public int compareTo(Student o) {
return (this.age-o.age==0)?this.name.compareTo(o.name):(this.age-o.age);
}
}
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Student>treeSet = new TreeSet<>();
Student s1 = new Student(18,"lingqingxia");
Student s2 = new Student(20,"yuelingsha");
Student s3 = new Student(28,"linghuchong");
Student s4 = new Student(30,"lisan");
Student s5 = new Student(30,"linjun");
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
for (Student student : treeSet) {
System.out.println("student = " + student);
}
}
}
5.3比较器Comparator的使用
用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写comparaTo(o1,o2)方法
public class TreeSet02 {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge()-o2.getAge();
return num==0?o1.getName().compareTo(o2.getName()):num;
}
});
Student s1 = new Student(18,"lingqingxia");
Student s2 = new Student(20,"yuelingsha");
Student s3 = new Student(28,"linghuchong");
Student s4 = new Student(30,"lisan");
Student s5 = new Student(30,"linjun");
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
for (Student student : treeSet) {
System.out.println("student = " + student);
}
}
}
6.1 泛型的概念
泛型: 是jdk5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
参数类型化: 将类型由原来的具体类型参数化,然后在使用/调用时传入具体的类型。
可用在类,方法,接口中,分别被称为泛型类,泛型方法,泛型接口
泛型定义格式:
- <类型>:指定一种类型的格式,这里的类型可以看作是形参
- <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开,这里的类型可以看成是形参
- 将来具体调用时给定的类型可以看成是实参,并且实参的类似只能是引用数据类型
6.2泛型类
泛型类的定义格式:
- 格式: 修饰符class类名<类型>{}
- 范例: public class Generic{} T为随便写为任意标识,常见如T,E,K,V等形式的参数常用于表示泛型
public class GenericTest01 {
public static void main(String[] args) {
Student<String>student = new Student<>("林青霞");
System.out.println(student.getT());
Student<Boolean>student1 = new Student<Boolean>(true);
System.out.println(student1.getT());
Student<Integer>student2 = new Student<>(120);
System.out.println(student2.getT());
}
}
6.3泛型方法
泛型方法的定义格式:
- 格式: 修饰符 <类型> 返回值类型 方法名(类型 方法名){}
- 范例: public void show(T t){}
public class Generic {
public static void main(String[] args) {
Generic generic = new Generic();
generic.show(120);
generic.show("hello");
generic.show(true);
}
public <T> void show(T t){
System.out.println(t);
}
}
6.4泛型接口
泛型接口的定义格式:
- 格式: 修饰符 interface 接口名 <类型> {}
- 范例: public interface Generic{}
public interface GenericDemo<T> {
void show(T t);
}
public class GenericDemoImpl<T> implements GenericDemo<T> {
@Override
public void show(T t) {
System.out.println("t = " + t);
}
}
public class GenericDemoTest {
public static void main(String[] args) {
GenericDemoImpl<String>genericDemo = new GenericDemoImpl<String>();
genericDemo.show("hello");
GenericDemoImpl<Integer>genericDemo1 = new GenericDemoImpl<Integer>();
genericDemo1.show(120);
GenericDemoImpl<Boolean>genericDemo2 = new GenericDemoImpl<Boolean>();
genericDemo2.show(true);
}
}
6.5类型通配符
类型通配符: <?>
List<?>: 表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
若不希望<List?>是任何类型List的父类,只希望它可以代表某一类泛型List的父类,可以使用类型通配符上限
- 类型通配符上限: <? extends类型>
- List<?extends Number> :它表示的类型是Number或者其子类型
若不希望<List?>是任何泛型List的子类,只希望它可以代表某一类泛型List的子类,可以使用类型通配符下限
- 类型通配符下限: <? super类型>
- List<? super Number>: 它表示的类型是Number或者其父类型
6.6可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
- 格式: 修饰符 返回值类型 方法名(数据类型…变量名){}
- 示例: public static int sum(int…a){}
注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
public class ArgsDemo {
public static void main(String[] args) {
System.out.println(sum(1, 2, 3, 4, 5));
}
private static int sum(int... num){
int sum = 0;
for (int i : num) {
sum +=i;
}
return sum;
}
}
6.7可变参数的常见方法
Arrays工具类中有一个静态方法: (不可增,不可删,可改)
public static <T>List<T>asList(T...a):返回由指定数组支持的固定大小的列表
List接口中有一个静态方法: (不可增,不可删,不可改)
public static <E> List<E> of(E...elements):返回包含任意数量元素的不可变列表
Set接口中有一个静态方法: (不可重复,不可增,不可删)
pubilc static <E>Set<E> of(E...elements):返回一个包含任意数量的不可变集合
7.1Map集合
Map集合概述
- Interface Map<K,V> K: 键的类型; V: 值的类型
- 将键映射到值的对象;不能包含重复的键,每个键可以映射到最多一个值
public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","林青霞");
map.put("002","张曼玉");
map.put("003","胡歌");
map.put("003","许嵩");
System.out.println(map);
}
}
7.2Map集合的常用方法
/*
V put(K key,V value); 添加元素
V remove(Object key); 根据键删除键值对元素
void clear() 移除所有元素
boolean containsKey(Object key); 判断集合是否包含指定的键
boolean containsValue(Object value) 判断结合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 结合的长度,也就是集合中键值对键值的个数
*/
public class MapDemo01 {
public static void main(String[] args) {
Map<String,String>map = new HashMap<>();
map.put("001","A");
map.put("002","B");
map.put("003","C");
System.out.println(map);
System.out.println(map.remove("001"));
System.out.println("map = " + map);
System.out.println(map.containsKey("002"));
System.out.println(map.containsValue("A"));
System.out.println(map.isEmpty());
System.out.println(map.size());
map.clear();
System.out.println("map = " + map);
}
}
7.3Map的功能集合
/*
Map集合的获取功能
V get(Object key); 根据键获取值
Set<K> keySet(): 获取所有键的集合
Collection(V) values(): 获取所有值的集合
*/
public class MapDemo03 {
public static void main(String[] args) {
Map<String,String>map = new HashMap<>();
map.put("001","A");
map.put("002","B");
map.put("003","C");
System.out.println(map.get("001"));
Set<String> stringSet = map.keySet();
for (String s : stringSet) {
System.out.println("s = " + s);
}
Collection<String>collection = map.values();
for (String s : collection) {
System.out.println("s = " + s);
}
}
}
7.4Map集合的遍历
public class MapDemo04 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","A");
map.put("002","B");
map.put("003","C");
Set<String> stringSet = map.keySet();
for (String s : stringSet) {
String value = map.get(s);
System.out.println("Key:"+s+","+"Value:"+value);
}
System.out.println("#################################");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("Key:"+key+","+"Value:"+value);
}
}
}
Map集合存储学生对象案例
public class MapDemo05 {
public static void main(String[] args) {
Map<String,Student> map = new HashMap<>();
map.put("001",new Student("msm","10"));
map.put("002",new Student("www","18"));
map.put("003",new Student("yyy","29"));
Set<String> strings = map.keySet();
for (String string : strings) {
System.out.println(string+","+map.get(string).getName()+","+map.get(string).getAge());
}
Set<Map.Entry<String, Student>> entries = map.entrySet();
for (Map.Entry<String, Student> entry : entries) {
String name = entry.getValue().getName();
String age = entry.getValue().getAge();
System.out.println(entry.getKey()+","+name+","+age);
}
}
}
案例 – 重写hashCode与equals
public class MapDemo06 {
public static void main(String[] args) {
Map<Student,String> map = new HashMap<>();
map.put(new Student("sms","20"),"001");
map.put(new Student("ywe","40"),"002");
map.put(new Student("poi","23"),"003");
map.put(new Student("poi","23"),"004"); //重写hashCode才覆盖
Set<Student> students = map.keySet();
// for (Student student : students) {
// System.out.println(student.getName()+","+student.getAge()+","+map.get(student));
// }
Set<Map.Entry<Student, String>> entries = map.entrySet();
for (Map.Entry<Student, String> entry : entries) {
System.out.println(entry.getKey().getName()+","+entry.getKey().getAge()+","+entry.getValue());
}
}
}
Map与ArrayList的嵌套使用案例
public class MapDemo07 {
public static void main(String[] args) {
ArrayList<HashMap<String,String>>arrayList = new ArrayList<>();
HashMap<String,String> map = new HashMap<>();
map.put("001","令狐冲");
map.put("002","岳灵珊");
HashMap<String,String> map1 = new HashMap<>();
map1.put("001","令狐冲");
map1.put("002","岳灵珊");
arrayList.add(map);
arrayList.add(map1);
for (HashMap<String, String> stringStringHashMap : arrayList) {
Set<String> strings = stringStringHashMap.keySet();
for (String string : strings) {
System.out.println(string+","+stringStringHashMap.get(string));
}
}
}
}
public void demo(){
HashMap<String, ArrayList<String>>hashMap = new HashMap<>();
ArrayList<String>arrayList = new ArrayList<String>();
arrayList.add("诸葛亮");
arrayList.add("曹操");
ArrayList<String>arrayList1 = new ArrayList<>();
arrayList1.add("松江");
arrayList1.add("公孙三娘");
ArrayList<String>arrayList2 = new ArrayList<>();
arrayList2.add("减小包");
arrayList2.add("林黛玉");
hashMap.put("sgyy",arrayList);
hashMap.put("shz",arrayList1);
hashMap.put("hlm",arrayList2);
Set<String> strings = hashMap.keySet();
for (String string : strings) {
System.out.println(string+","+hashMap.get(string));
}
}
统计字符串中字符的出现次数
public static void demo(){
Scanner input = new Scanner(System.in);
String str =input.nextLine();
HashMap<Character,Integer>hashMap = new HashMap<>();
int length = str.length();
for (int i = 0; i < length; i++) {
char ch = str.charAt(i);
if (hashMap.get(ch) == null){
hashMap.put(ch,1);
}else {
hashMap.put(ch,hashMap.get(ch)+1);
}
}
Set<Character> characters = hashMap.keySet();
for (Character character : characters) {
System.out.print(character+"("+hashMap.get(character)+")");
}
}
}
8.1Properties
概述:
- 是一个Map体系的的集合类
- Propertie可以保存到流中或从流中加载
public class properity {
@Test
public void demo(){
Properties properties = new Properties();
properties.put("001","林青霞");
properties.put("002","风清扬");
properties.put("003","张三");
Set<Object> objects = properties.keySet();
for (Object object : objects) {
System.out.println(object+","+properties.get(object));
}
}
}
Properties作为集合的特有方法:
- Object setProperty(String key,String value); 设置集合的键和值,都是String类型,底层调用Hashtable方法put
- String getProperty(String key); 使用此属性列表中指定的键搜索属性
- SetstringPropertyName(); 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
@Test
public void demo1(){
Properties properties = new Properties();
properties.setProperty("001","林青霞");
properties.setProperty("002","风晴雪");
properties.setProperty("003","百里守约");
System.out.println("properties = " + properties);
System.out.println(properties.getProperty("001"));
Set<String> strings = properties.stringPropertyNames();
for (String string : strings) {
System.out.println(string+","+properties.getProperty(string));
}
}
}
与io流结合的方法
- void load(Reader reader) 从输入字符读取属性列表(键和元素对)
- void store(Writer write,String comments):将此属性列表(键和元素对)写入Properties表中,以适合使用load(Reader)方法的格式写入输出字符流
@Test
public void demo2() throws IOException {
Properties properties = new Properties();
properties.put("001","林青霞");
properties.put("002","风清扬");
properties.put("003","百里屠苏");
properties.store(new FileWriter("./src/cn/yue/serializable/1.properties"),null);
Properties prop = new Properties();
prop.load(new FileReader("./src/cn/yue/serializable/1.properties"));
System.out.println("prop = " + prop);
}
}
9.1Colections概述和使用
- 是针对集合操作的工具类
Collections类的常用方法
- public static <T extens Comparable<? super>>void sort(List list):将指定的列表按升序排序
- public static void reverse(List<? list>): 反转指定列表中的元素的顺序
- public static void shuffle(List<?> list): 使用默认的随机源随机排列指定的列表
public void demo(){
List<Integer>list = new ArrayList<>();
list.add(80);
list.add(23);
list.add(90);
list.add(34);
list.add(200);
Collections.sort(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println("list = " + list);
}
}
综合案例 — 斗地主
public class DouDiZhuUpgrade {
@Test
public void demo(){
HashMap<Integer,String>hashMap = new HashMap<>();
ArrayList<Integer> arrayList = new ArrayList<>();
String[]colors = {"♠","♥","♣","♦"};
String[]numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
int index = 0;
for (String number : numbers) {
for (String color : colors) {
arrayList.add(index);
hashMap.put(index++,color+number);
}
}
arrayList.add(index);
hashMap.put(index++,"小王");
arrayList.add(index);
hashMap.put(index,"大王");
Collections.shuffle(arrayList);
TreeSet<Integer> DP = new TreeSet<>();
TreeSet<Integer> LQX = new TreeSet<>();
TreeSet<Integer> WW = new TreeSet<>();
TreeSet<Integer> FQY = new TreeSet<>();
for (int i = 0; i < arrayList.size(); i++) {
if (i>= arrayList.size() -3){
DP.add(i);
}else if(i % 3 ==0){
LQX.add(i);
}else if(i % 3 == 1){
FQY.add(i);
}else if(i % 3 == 2){
WW.add(i);
}
}
System.out.println(LQX);
lookPoker(hashMap,LQX);
lookPoker(hashMap,WW);
lookPoker(hashMap,FQY);
lookPoker(hashMap,DP);
}
public static void lookPoker(HashMap<Integer,String>hashMap, @NotNull TreeSet<Integer>treeSet){
for (Integer integer : treeSet) {
System.out.print(hashMap.get(integer)+" ");
}
System.out.println();
}
}
DP = new TreeSet<>();
TreeSet LQX = new TreeSet<>();
TreeSet WW = new TreeSet<>();
TreeSet FQY = new TreeSet<>();
for (int i = 0; i < arrayList.size(); i++) {
if (i>= arrayList.size() -3){
DP.add(i);
}else if(i % 3 ==0){
LQX.add(i);
}else if(i % 3 == 1){
FQY.add(i);
}else if(i % 3 == 2){
WW.add(i);
}
}
System.out.println(LQX);
lookPoker(hashMap,LQX);
lookPoker(hashMap,WW);
lookPoker(hashMap,FQY);
lookPoker(hashMap,DP);
}
public static void lookPoker(HashMap<Integer,String>hashMap, @NotNull TreeSet<Integer>treeSet){
for (Integer integer : treeSet) {
System.out.print(hashMap.get(integer)+" ");
}
System.out.println();
}
}