1.Collection集合
集合和数组的区别?
- 数组的长度是固定的, 集合的长度是可变的
- 数组中存储的数据都是同一类型的数据。集合存储的是对象,而且对象的类型可以不一致
集合框架
单列集合
java.util.Collection
Collection:单列集合的跟接口,用于存储一系列的规则的元素
两个子接口:
- java.util.List: List中元素是有序,元素可重复
- 实现类:java.util.ArrayList, java.util.LinkedList
- Java.util.Set: Set中元素无序,不重复
- 实现类:java.util.HashSet, java.util.TreeSet
Collection集合的常用功能
Collection是所有单列集合的父接口,因此定义了一些通过方法
public boolean add(E, e)
:添加元素到集合中public void clear()
:清空集合中所有的元素public boolean remove(E, e)
:删除指定的元素public boolean contains(E, e)
:判断当前集合是否存在给定的元素public boolean isEmpty()
:判断当前集合是否为空public int size()
:返回集合中元素的个数public Object[] toArray()
:把集合的元素存储到数组中import java.util.ArrayList; import java.util.Colleaction; public class Demo{ public static void main(String[] args){ // 创建集合对象,使用多态 Collection<String> coll new ArrayList<String>(); //使用方法 // 添加 coll.add("杨幂").add("刘亦菲").add("唐嫣").add("胡珺"); System.out.println(coll); // 判断是否在集合中 System.out.println("判断胡珺是否在集合中"+coll.contains("胡珺")); // 判断集合是否为空 System.out.println(coll.isEmpty()); // 集合中有多少个元素 System.out.println(coll.sixe()); // 删除指定的元素 coll.remove("胡珺"); // 集合存储到数组中 Object[] object = coll.toArray(); //遍历数组 for(int i=0;i<object.length;i++){ System.out.println(i); } // 清空集合 coll.clean(); } }
2.Iterator迭代器
迭代
- 在集合中获取元素之前进行判断集合中有没有元素,如果有取出来,继续进行判断,继续取出来,知道集合元素全部取出
Iterator的常用方法
public E next()
:返回迭代的下一个元素public boolean hasNext()
:如果有元素可以迭代,则返回True
public class Demo{ public static void main(String[] args){ //使用多肽创建集合 Collection<String> coll = new ArrayList<String>(); // 添加元素 coll.add("杨幂").add("胡珺").add("程锐"); //使用迭代器进行遍历 Iterator<String> it = coll.iterator(); // 泛型值得是: 迭代出来的数据类型 while(it.hasNext()){//判断是否有迭代元素 String s = it.next(); //获取迭代的元素 System.out.println(s); } } }
增强for
格式:
for(元素的数据类型 变量:Collection集合或者数组){ //操作代码 }
它用于变量Collection和数组, 不要在遍历的时候对集合元素进行曾删操作
public class Demo{ public static void main(String[] args){ int[] arr = {1,2,3,4,5}; for(int i:arr){ System.out.println(i); } } }
public class Demo{ public static void main(String[] args){ Collection<String> coll = new ArrayList<String>(); coll.add("112"); coll.add("113"); coll.add("114"); for(String s:coll){ System.out.println(s); } } }
只针对Collection和数组, 用于遍历
3.泛型
在从集合中存取数据,数据将被提升为Object类型,当我们取出一个的对象,进行操作,这个时候需要类型转换
泛型:可以再类或者是方法中预支的使用未知的数据类型
一般在创建对象是,当没有指定类型的时候,默认是Object类型
泛型好处
- 将运行售后的ClassCastException,转移到了编译时期变成编译失败
- 避免了类型强转的麻烦
public class Demo{ public static void main(String[] args){ collection<String> coll = new ArrayList<String>(); coll.add("abd"); coll.add("aaa"); //coll.add(5); 当集合明确类型后, 存放类型不一致就会编译错误 // 集合已经明确的具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样知道具体遍历元素类型 Iterator<String> it = coll.iterator(); while(it.hasNext()){ //当使用Iterator控制的元素类型之后,就不要强转了,获取的元素就是String类型 String str = it.next(); System.out.println(str); } } }
泛型是数据泛型的一部分,我们将类名和泛型合并起来一起看做数据类型
泛型的定义与使用
我们在集合中通常使用到了泛型
泛型,用来灵活的将数据类型应用到不同的类,方法,接口当中。将数据类型作为参数进行传递
定义和使用含有泛型的类
定义格式:
修饰符 class 类名<代表泛型的变量>{}
demo
ArrayList集合; public class ArrayList<E>{ public boolean add(E e){} public E get(int index){} .... }
使用泛型:即什么时候确定泛型
在创建对象的时候使用泛型
例如:ArrayList
此时就可以理解变量E的值就是String类型,那么理解为
public class ArrayList<String>{ public boolean add(String e){} public String get(int index){} }
再例如,ArrayList
此时理解为E的值就是Integer
public class ArrayList<Integer>{ public boolean add(Integer e){} public Integer get(int index){} }
demo
public class MyGenericClass<MVP>{ //没有MVP类型,在这里带变得是一种未知类型, 传递什么类型就是什么类型 private MVP mvp; public void setMVP(MVP mvp){ this.mvp = mvp; } public MVP getMVP(){ return mvp; } }
使用
public class GenericClassDemo{ public static main(String[] args){ // 创建一个泛型为Integer的类 MyGenericClass<Integer> myNum = new MyGenericClass<Integer>(); myNum.setMVP(124); Integer mvpNum = myNum.getMVP(); System.out.println(mvpNum); //创建一个泛型为String的类 MyGenericClass<String> myStr = new MyGenericClass<String>(); myNum.setMVP("哈哈"); String mvpStr = myStr.getMVP(); System.out.println(mvpStr); } }
含有泛型的方法
定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){}
例如
public class MyGenericMethod{ public <MVP> void show(MVP mvp){ System.out.println(mvp.getClass()); } public <MVP> MVP show2(MVP mvp){ return mvp; } }
使用格式: 调用方法时,确定泛型的类型
public class GenericMethodDemo{ public static void main(String[] args){ //创建对象 MyGenericMethod mm = new MyGenericMethod(); //演示看方法提示 mm.show("aaa"); mm.show(12); } }
含有泛型的接口
定义格式:
修饰符 Interface接口名 <代表泛型的变量>{}
例如
public interface MyGenericInterFace<E>{ public abstract void add(E e); public abstract E getE(); }
使用格式:
1.定义类是确定泛型的类型
例如
public class MyImpl implements MyGenericInterFace<String>{ @Override public void add(String e){ //... } @Override public void getE(){ return null; } } //此时泛型E的值就是String类型
2.始终不确定泛型的类型,直接创建对象时,确定泛型的类型
例如
public class MyImpl<E> implements MyGenericInterFace<E>{ @Override public void add(E e){ //... } @Override public void getE(){ return null; } }
确定泛型:
public class GenericInterFace{ public static void main(String[] args){ MyImpl<String> my = new MyImpl<String>(); my.add("aaa"); } }
泛型通配符
当我们使用泛型或者是接口的时候,传递的数据中,泛型类型不确定,可以通过通配符<?>表示,但是一旦使用泛型的通配符之后,只能使用Object类中的共性方法,集合中元素自身的方法无法使用。
通配符的基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用??表示未知通配符
此时只接受数据,不能再集合中存储数据
例子:
public class Demo{ public static void main(String[] args){ Collection<Integer> list1 = new ArrayList<Integer>(); getElement(list1); Collection<String> list2 = new ArrayList<String>(); getElement(list2); } public static void getElement(Collection<?> coll){ // ? 代表可以接受任意类型 } }
泛型不存在继承关系,Collection
通配符高级使用—受限泛型
之前在设置泛型的时候,实际上是可以任意设置的,只要是类就可以,但是Java中泛型可以指定一个上限和下限。
泛型的上限:
- 格式:类型名称 <? extends 类> 对象名称
- 意义:只能接受该类型及其子类
泛型的下限:
- 格式:类型名称 <? super 类> 对象名称
- 意义:只能接受该类型及其父类型
比如:Object类,String类,Number类,Integer类,其中Number是Integer的父类
public class Demo{ public static void main(String[] args){ Collection<Integer> list1 = new ArrayList<Integer>(); Collection<String> list2 = new ArrayList<String>(); Collection<Number> list3 = new ArrayList<Number>(); Collection<Object> list1 = new ArrayList<Object>(); } getElement(list1); getElement(list2); //报错 getElement(list3); getElement(list4); //报错 getElement2(list1);//报错 getElement2(list2);//报错 getElement2(list3); getElement2(list4); // 泛型的上限: 此时的泛型必须是Number类型或者是Number类型的子类 public static void getElement(Collection<? extends Number> coll){}; // 泛型的下限: 此时的泛型必须是Number类型或者是Number类型的父类 public static void getElement2(Collection<? super Number> coll){}; }
4.Map集合
Collection
中的集合,元素是孤立存在的(单身),向集合中存储元素采用一个个元素的方式存储。Map
中的集合,元素是成对存在的(Python中的字典),每个元素有键和值组成,通过键进行找到值。- Map是双列集合
注意:Map中的集合不能有重复的键,值可以重复,但键唯一
Map常用子类
HashMap
存储数据采用的是哈希表结构,元素的存储顺序不能保证一直,保证了键唯一,不重复,需要重写键的hashCode()方法,equals()方法。LinkedHashMap
存储数据采用哈希表+链表结构,通过链表结构可以保障元素存储顺序一直;用过哈希可以保障键的唯一,需要重写hashCode()方法,equals()方法。
Map中的集合有两个泛型变量,在使用的时候,需要为两个变量赋予数据类型。两个变量数据类型可以相同,可以不同。
Map中常用方法
public V put(K key, V value)
:将指定的键与指定的值添加到集合中public V remove(Object key)
:把指定的键对应的键值对元素在集合中删除,返回删除元素的值。public V get(Object key)
:根据指定的键,在Map集合中获取对应的值public Set<K> keySet()
:获取Map集合中所有的键,存储到Set集合中public Set<Map.Entry<K,V>>entrySet()
:获取到Map集合中所有的键值对对象的集合(Set集合)
demo
import java.util.Map; public class MapDemo{ public static void main(String[] args){ // 创建map对象 HashMap<String, String> map = new HashMap<String, String>(); // 添加元素到集合 map.put("黄晓明","baby"); map.put("刘德猛","胡珺"); map.put("邓超","孙俪"); //remove System.out.println(map.remove("邓超")); //查看刘德猛的老婆是谁 System.out.println(map.get("刘德猛")); } }
注意:使用put方法,若指定的键在集合中没有,则返回值为null,并将指定的键添加到集合中
若指定的键存在,则返回值为集合中对应的值(该值为替换前的值),并将指定键对应的值换成指定的新值
Map集合中遍历键找值方法
键找值方法:通过元素中的键,获取键对应的值
分析步骤:
获取Map中的所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键,方法:
keyset()
遍历Set集合,得到每一个键
依据键取值方法:
get(K key)
public class Demo{ public static void main(String[] args){ //创建Map集合对象 HashMap<String,String> map = new HashMap<String,String>(); //添加元素到集合中 map.put("胡歌","霍建华"); map.put("黄晓明","baby"); map.put("刘德猛","胡珺"); map.put("邓超","孙俪"); // 获取所有的键 Set<String> keys = map.keySet(); // 遍历键列表 for(String key:keys){ // 获取对应的value值 String value = map.get(key); System.out.println(key+":"+value); } } }
Entry键值对对象
Map是两种对象,一种是Key
键,一种是Value
值,Entry
是将键值对进行了封装,即键值对对象,这样遍历Map
集合中,就可以从一个键值对获取对应的值和键。
public K getKey()
:获取Entry中对象的键public V getValue()
: 获取Entry中对象的值public Set<Map.Entry<K, V>> entrySet()
: 获取Map集合中所有的键值对对象的集合(Set集合)
Map集合遍历键值对方式
键值对方式:通过集合中每个键值对(Entry)对象,获取键值对(Entry)中的键和值
操作步骤:
- 获取Map集合中,所有的键值对对象,以set集合形式返回,
entrySet()
方法 - 遍历包含键值对象Set集合,得到每一个键值对对象
- 通过键值对对象,过去Entry中的键和值,方法:
getKey(), getValue()
方法
public class Demo{ public static void main(String[] args){ // 创建Map集合对象 HashMap<String, String> map = new HashMap<String, String>(); // Map添加元素 map.put("胡歌", "霍建华"); map.put("郭德纲", "于谦"); map.put("薛之谦","大张伟"); // 获取所有的Entry对象 Set<Entry<String, String>> entrySet = map.entrySet(); // 遍历得到每一个entry对象 for(Entry<String,String> entry:entrySet){ //解析 String Key = entry.getKey(); String Value = entry.getValue(); System.out.println(Key+"的值是"+Value); } } }
HashMap存储自定义类型键值对
练习,每位学生(姓名和年龄)都有自己的家庭住址,那么既然有对应关系,则将学生对象和家庭住址存储到map集合中,学生作为键,家庭住址作为值。
注意:学生姓名相同并且年龄相同则视为同一个学生
编写学生类:
public class Student{ private String name; private int age; // 构造方法 public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } // get方法 public String getName(){ return name; } public int getAge(){ return age; } // set方法 public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } // 重写equal方法 @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 && Object.equals(name, student.name); } @Override public int HashCode(){ return Objects.hash(name, age); } }
测试类
public class HashMapTest{ public static void main(String[] args){ Map<Student, String> map = new HashMap<Student, String>(); //添加元素 map.put(new Student("lisi", 15), "北京"); map.put(new Student("wangwu", 16), "上海"); map.put(new Student("zhaoliu", 17), "深圳"); // 取出元素 Set<Student> keySet = map.keySet(); for(Student key: keySet){ String value = map.get(key); System.out.println(key.toString()+"..."+value); } } }
LinkedHashMap
LinkedHashMap下面一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构
public class LinkedHashMap{ public static void main(String[] args){ LinkedHashMap<String, String> map = new LinkedHashMap<String, String>(); map.put("邓超", "孙俪"); map.put("李晨", "范冰冰"); map.put("刘德华", "朱丽倩"); Set<Entry<String, String>> entrySet = map.entrySet(); for(Entry<String, String> entry:entrySet){ System.out.println(entry.getKey()+"..."+entry.getValue()); } } }
来源:https://www.cnblogs.com/liudemeng/p/11523609.html