粗糙的集合相关的知识点

1>List集合特有的功能
void add(int index,E element) 在指定位置添加元素
E remove(int index) 删除指定位置的元素
E get(int index) 获取指定位置元素
E set(int index,E element) 修改指定位置的元素

2> List集合的遍历
掌握size和get方法的应用
List list = new ArrayList();
list.add(new Student(“aa”,23));
list.add(new Student(“ab”,23));
list.add(new Student(“ac”,23));

for(int i=0;i<list.size();i++){
Object obj = list.get(i);
sysout(obj);
}

3>并发修改异常
》如果对一个集合要一边遍历,一边添加元素,使用ListIterator这个类来实现
》ListIterator提供一个add方法来添加元素,
》ListIterator与Iterator这两个接口的关系继承

4>ListIterator的其它方法
hasPrevious方法 : 判断是否有上一个元素
previous方法: 获取上一个元素

=代码样式===========

ListIterator iterator = list.listIterator();
while(iterator.hasNext()){
	Object obj = iterator.next();
	System.out.println(obj);
}
System.out.println("=========");
while(iterator.hasPrevious()){//判断是否有上一个元素
	//取出上一个元素
	Object obj =  iterator.previous();
	System.out.println(obj);
}

===========================================================================

  1. Vector
    Vector实现List接口,方法基本上都添加了同步的声明,所以它是线程安全,性能差
    Vector在开发中用的比较少

  2. 数据结构-数组和链表
    数组:查找和修改快,增加删除慢
    链表:查找和修改慢,增加删除快

7. 集合之间的区别:

一、Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的

二、ArrayList和LinkedList的区别
ArrayList底层是数组实现,查询和修改快
LinkedList底层是链表结构实现,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的

三、List有三个子类,我们到底使用谁呢?
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList

8. 去除ArrayList中重复元素

去除字符串:
思路-创建一个新集合,遍历旧的集合,把每一个元素添加到新的集合
在添加到新的集合前,要判断这个元素是否在新的集合中已经存在(contains方法)

去除自定义对象:
思路-创建一个新集合,遍历旧的集合,把每一个元素添加到新的集合
在添加到新的集合前,要判断这个元素是否在新的集合中已经存在(contains方法)
还要重写equals方法

  1. LinkedList的使用
    addFirst(E e) 把元素添加到第一个位置
    addLast(E e) 把元素添加到最后的位置
    getFirst() 获取第一个元素
    getLast() 获取第二个元素
    removeFirst() 删除第一个元素
    public E removeLast() 移除第一个元素

  2. 栈和队列
    栈:先进后出
    队列:先进先出

11>用LinkedList模型栈数据结构
=代码==========
class Stack{

//创建一个集合
LinkedList list = new LinkedList();

//进栈
public void in(Object obj){
	//把元素添加集合
	list.addFirst(obj);//集合前面的是栈顶,后面是栈底
	//list.addLast(obj);
}

//出栈
public Object out(){
	return list.removeFirst();
}

}

  1. 用LinkedList的pop和push方法
    pop:出栈
    push:进栈

13>泛型集合
/**

  • 泛型:
  • 1.泛型的作用:把类型明确的工作推前到创建对象或者调用方法的时候。
  • 2.泛型是一种参数化类型,把类型当作参数一样传递来明确集合的元素类型
  • 泛型好处
  • 1.提高安全性(将运行期的错误转换到编译期)
  • 2.省去强转的麻烦
    /
    /
    **
  • 1.如果集合添加基本数据类型,内部会提升为包装类型
  • int -> Integer
  • double -> Double
  • 2.List list = new ArrayList(); 这样声明一个集合对象,默认是可以添加任何类型的元素
  • 3.如果在声明集合时,不添加泛型,就会有安全隐患(类型转换异常)
  • 4.声明一个泛型集合:List list = new ArrayList();
  • 代表list只能存字符串元素

*/

1》泛型迭代器
Iterator iterator;
Iterator iterator;

2》泛型注意事项
// 1.默认声明一个泛型集合,前后类型要一至
List list1 = new ArrayList();

// 2.这样声明前后类型不一至是不可以的
//不可以前面写父类,后面写子类
//List list2 = new ArrayList();

// 3.集合泛型的声明,可以只声明前面的泛型,jdk1.7的新特性:菱形泛型,开发时建议还是写成前后一至
//1.6 1.5的jdk不能写菱形泛型
List list3 = new ArrayList<>();

// 4.集合声明的泛型,代表此类或者子类都可以成为集合的元素,eg: Person -> Student
List list4 = new ArrayList();

// 5.声明的泛型类型一定是引用数据类型(类)
//泛型是基本数据类型
//List list6 = new ArrayList();
List list6 = new ArrayList();

3》泛型的由来
解决类型转换异常

04》声明泛型类和泛型方法
**

  • 掌握:
  • 如何声明一个泛型类和方法
  • 1.声明一个泛型类
  • class Tool
  • 声明泛型方法格式: public 返回类型(T) 方法名(泛型类型T 变量名)
  • 2.声明一个泛型方法(无返回值,有泛型参数)
  • public void print(T t)
  • 3.声明一个泛型方法(有返回值,无参数)
  • public T get(int index)
  • 4.声明一个泛型属性
  • private T o;
    public T getO() {
    return o;
    }
    public void setO(T o) {
    this.o = o;
    }

*/

05》泛型高级之通配符
// 1.泛型通配符<?> 一般在声明变量类型时使用
// 任意类型,如果没有明确,那么就是Object以及任意的Java类了
//打印集合对象
public static void print(List<?> list){
System.out.println(list);
}

// 2.? extends E 【E是父类,?子类】
// 向下限定,E及其子类
/**
* addAll(Collection<? extends Person> c)
* 添加的集合可以是 Person类型【List list4】,或者是Person的子类【List list6】
*/
//List list5 = new ArrayList();

	/**
	 * addAll(Collection<? extends Student> c)
	 * 添加的集合可以是 Student类型【List<Student> list6】,或者是Student的子类【List<Person> list4】
	 */
	List<Student> list5 = new ArrayList<Student>();
  1. ? super E 【?是父类,E子类】
    向上限定,E及其父类

04》增强for循环
简体数组和集合遍历
格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}

   int[] arr1 = {120,110,119};
    for(int num : arr1){
    	System.out.println(num);
    }

//2.集合
List<String> list = new ArrayList<String>();
list.add("小子");
list.add("孙子");
list.add("老子");

int i = 0;
for(String str : list){
	i++;
	System.out.println("第" + i + "个元素:" + str);
}

05》三种迭代能否删除元素
普通for循环,可以删除,但是索引要(–减减 )
迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
增强for循环不能删除

06》静态导入[很少用]
静态导入是只导入类的静态方法
import static 包名+类名+方法名;

07》可变参数
可变参数,就是调用方法的时候,可以传n个参数
test1(int … nums);//传n个数字
test2(Object … objs);//传n个任意对象

注意:如果方法有多个参数名,可变参数名必须要放在最后

08》Arrays.asList方法:把数组转成集合
List<String> list1 = Arrays.asList("Gosling","Lucy","Lily");
System.out.println(list1);
		
List<Student> list2 = Arrays.asList(new Student(),new Student(),new Student());
System.out.println(list2);


13》Collection的toArray方法:把集合的元素 添加到 指定数组中
		Collection<String> col = new ArrayList<String>();
		col.add("Gosling");
		col.add("gyf");
		
		//声明一个字符串数组
		String[] strs = new String[2];
	
		System.out.println("===================");
		//把集合里的元素 存在 指定的数组中
		col.toArray(strs);
		
		for(String str : strs){
			System.out.println(str);

09》集合嵌套之List嵌套List
案例需求
1.一个班的n学生是一个集合
2.一个学校n班也是一个集合
3.如何将这些数据用一个集合来表示
//1、用集合来表示两个班级
		List<Student> java1 = new ArrayList<Student>();
		java1.add(new Student("小刘", 18));
		java1.add(new Student("小张", 18));
		java1.add(new Student("小关", 18));
		
		List<Student> java2 = new ArrayList<Student>();
		java2.add(new Student("李某某", 18));
		java2.add(new Student("黄某某", 18));
		java2.add(new Student("李某某", 18));
		
		//2.用集合来表示学校school
		List<List<Student>> school = new ArrayList<List<Student>>();
		school.add(java1);
		school.add(java2);
		
		//3.遍历
		//3.1遍历班级
		for(List<Student> stus : school){
			System.out.println("班级...");
			//3.2 遍历学生
			for(Student stu : stus){
				System.out.println(stu);
			}
		}

Set:接口

  • 1.一个不包含重复元素的 collection。
  • 2.最多包含一个 null 元素
  • 3.一般使用它实现类:HashSet,LinkedHashSet,TreeSet
  • 4.Set集合存和取的顺序不一样,【每一次取的顺序都可能不一样】

List:接口

  • 1.List是可存储相同元素
  • 2.List存的取的元素顺序是一样**

HashSet

  • 1.此类实现 Set 接口
  • 2.由哈希表(实际上是一个 HashMap 实例)支持。
  • 3.它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
  • 4.此类允许使用 null 元素。

set遍历方法
Set遍历一、增强for循环
Set遍历二、迭代器

  1. hashCode与equals的原理
    通过set集合的add方法添加元素时,内部会调用hashcode和equals方法
    如果比较的hashcode的值是一样的话,会调用equals方法,equals方法返回true,就不存元素,返回false就存元素
    如果比较的hashcode的值不一样,就直接存元素

5》hashCode与equals的优化
/**

  • 例子:
    Person属性:
    -name
    -age
  • 1.如果名字不一样,就不需要调用equals方法,从而优化代码
  • return this.name.hashCode()
  • 2.hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    return this.name.hashCode() + this.age;
    */
  1. LinkedHashSet
    LinkedHashSet是HashSet的子类
    LinkedHashSet 存和取的顺序是一样

  2. TreeSet
    TreeSet是一种能排序集合
    默认情况下,TreeSet存Integer时,由小到大排序
    默认情况下,TreeSet存String时,字母的由小到大排序
    Integer和String这两个类都内部实现了comparable接口

  3. TreeSet保存自定义对象

>自定义对象必须实现comparable接口?

实现这个接口的目的是告诉TreeSet你的元素的排序规则 >实现了comparable接口的类,要实现compareTo方法
compareTo方法:
0-只存一个元素,第一个元素
-1:存的顺序倒序
1:存的顺序正序

9. TreeSet排序的原理 TreeSet是使用二叉权存数据

0:不存
负数:存在左边
正数:存在右边

  1. Person 要按年龄和名字进行排序

    public int compareTo(Person other) {
    	//1.按年龄的由小到大排序
    	int num =  this.age - other.age;
    	System.out.println(this.name + "..比较..." + other.name + " 年龄差:" + num);
    	
    	//if(num == 0) num = 1;
    	
    //2.如果年龄一样,根据名字排序 [字符串一样,比较的结果也是0]
    if(num == 0){
    	num = this.name.compareTo(other.name);
    }
    
    return num;
    

    }

  2. Student 要按名字的长度,名字和年龄进行排序

    public int compareTo(Student other) {
    // TODO Auto-generated method stub
    //1.按照姓名长度
    int num = this.name.length() - other.name.length();

    	//2.字母排序
    	/*if(num == 0){
    		num = this.name.compareTo(other.name);//由小到大字母排序
    		//num = other.name.compareTo(this.name);//由大到小字母排序
    	}*/
    	
    	num = (num == 0) ? this.name.compareTo(other.name) : num;	
    	//3.年龄排序
    	/*if(num == 0){
    		num = this.age - other.age;//由小到大
    	}*/
    	num = (num == 0) ? this.age - other.age : num;
    	
    	return num;
    }
    

01.TreeSet的Comparator排序方式
/**

  • TreeSet的排序方式有2种
  • 1.自然顺序(Comparable)
  • 2.比较器顺序(Comparator)
  • public TreeSet(Comparator<? super E> comparator)
  • 使用场景:如果元素的类型是final类型,不被重写,这个时候选择Comparator排序方式
  • 3.如果希望有相同的元素存在,在compareTo或者compare方法,返回1就行了。

*/

02.TreeSet排序原理总结

TreeSet的特点:
–TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
–TreeSet排序方式有两种自然顺序和比较器顺序
自然顺序(Comparable)
TreeSet类的add()方法中会把存入的对象提升为Comparable类型
调用对象的compareTo()方法和集合中的对象比较
根据compareTo()方法返回的结果进行存储
比较器顺序(Comparator)
创建TreeSet的时候可以制定 一个Comparator
如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的规则比较
add()方法内部会自动调用Comparator接口中compare()方法排序
调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

–两种比较方式的区别
1.TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
2.TreeSet如果传入Comparator, 就优先按照Comparator

03.案例:在一个集合中存储了无序并且重复的字符串,让其有序(字母顺序),而且还不能去除重复
Set<String> names = new TreeSet<String>(new Comparator<String>() {

	@Override
	public int compare(String o1, String o2) {
		// TODO Auto-generated method stub
		int num = o1.compareTo(o2);//由小到大
		num = num == 0 ? 1 : num;//保存同名元素
		return num;
	}
});
names.add("orange");
names.add("banana");
names.add("apple");
names.add("banana");

04.案例:从键盘输入接收多个整数, 直到输入quit时结束输入. 把所有输入的整数倒序排列打印
/**

  • 掌握:
  • 1.数字的倒序实现
  • 2.把str转成int

*/

public static void main(String[] args) {
	//从键盘输入接收多个整数, 直到输入quit时结束输入. 
	//把所有输入的整数倒序[由大到小]排列打印
	
	//1.创建TreeSet集合
	Set<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {

		@Override
		public int compare(Integer o1, Integer o2) {
			// TODO Auto-generated method stub
			return o2 - o1;//倒序排列
		}
	});
	
	//2.接收整数存在TreeSet中
	Scanner scanner = new Scanner(System.in);
	System.out.println("请多次输入数字按回车,如果退出请输入quit");
	while(true){
		//接受用户的输入
		String str = scanner.nextLine();
		if(str.equals("quit")){
			break;//退出死循环
		}
		//Integer.parseInt(str) 把字符串转成int
		set.add(Integer.parseInt(str));
	}
	
	//3.打印集合
	for(Integer i : set){
		System.out.println(i);
	}
}

}

05.键盘录入学生信息按照总分排序后输出在控制台
/**

  • 1.创建学生类

  • 添加3个学科(语文,数学,英语)成绩属性

  • 添加名字属性

  • 在有参构造方法中把总分算好

  • 2.把n个学生添加到TreeSet中

  • 3.TreeSet要进行总分排序
    @Override
    public int compareTo(Student o) {
    // TODO Auto-generated method stub
    //总分排序【由大到小】
    int num = o.totalScore - this.totalScore;

     //如果总分一样,就按照名字排序
     num = num == 0 ? this.name.compareTo(o.name) : num;
     
     //同名的学生可能有些没法排序
     num = num == 0 ? 1 : num;
     return num;
    
  1. Map介绍
    Map是属于java.util的一个接口Map<K,V>
    类型参数:
    K - 映射所维护的键的类型
    V - 映射值的类型
    Map是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

Map接口和Collection接口的不同
–Map是双列的,Collection是单列的
–Map的键唯一,Collection的Set是唯一的,List不是惟一的

Map:有几个常用的子类HashMap,LinkedHashMap,TreeMap,Hashtable,Properites

  1. Map的功能
    a>添加功能
    V put(K key,V value):添加元素。
    如果键是第一次存储,就直接存储元素,返回null
    如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
    b>删除功能
    void clear():移除所有的键值对元素
    V remove(Object key):根据键删除键值对元素,并把值返回
    c>判断功能
    boolean containsKey(Object key):判断集合是否包含指定的键
    boolean containsValue(Object value):判断集合是否包含指定的值
    boolean isEmpty():判断集合是否为空
    d>获取功能
    V get(Object key):根据键获取值
    Set keySet():获取集合中所有键的集合
    Collection values():获取集合中所有值的集合
    e>长度功能
    int size():返回集合中的键值对的个数

  2. HashMap使用注意事项
    声明HashMap时的键值可以是任意对象
    如果有重复的键,会把以前的替换
    值能为空
    键能为空,但这样写没什么意义
    put方法的返回值
    如果键是第一次存储,就直接存储元素,返回null
    如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

  3. Map的遍历,有两种方式
    a>Map集合的遍历一(键找值)
    通过key得到value
    通过entry得到key和value
    例子:
    1.创建Map对象
    Map<String,String> map = new HashMap<String,String>();
    map.put(“name”, “刘姐”);
    map.put(“age”, “48”);
    map.put(“gender”, “女”);
    map.put(“height”, “1.62”);

    //3.遍历
    //3.1获取map所有键
    Set keys = map.keySet();
    //3.2遍历键
    for(String key : keys){
    //3.3 通过key获取值
    String value = map.get(key);

    //打印key&value
    System.out.println(key + " : " + value);
    

    }
    键值对对象找键和值源码分析
    1.Map.Entry理解成"键值对对象"
    2.Map.Entry是一个接口,它的实现类是HashMap$Node
    3.Map.Entry是有个key和value属性,通过get方法可以取值
    4.遍历Entry的两种方法,通过迭代器和for增强

  4. 遍 历
    Set<Entry<String, Integer>> entries = map.entrySet();

         //2.1通过增强for循环来遍历Set
         /*for(Entry<String, Integer> entry : entries){
         	//Map.Entry 的实现类HashMap$Node 
         	System.out.println(entry.getClass());
         	System.out.println(entry.getKey() + "---" + entry.getValue());
         }*/
         //2.2 通过迭代器来遍历Set
    

    Iterator<Entry<String, Integer>> iterator = entries.iterator();
    while(iterator.hasNext()){
    Entry<String, Integer> entry = iterator.next();
    System.out.println(entry.getKey() + “—” + entry.getValue());
    }

    3.案例 :HashMap集合键是Student,值是String

    public class Demo01 {
    public static void main(String[] args) {
    /* 案例 :HashMap集合键是Student,值是String
    键是学生对象,代表每一个学生
    值是字符串对象,代表学生归属地

     	注意事项:
     	1.打印的key是student的toString方法返回的字符串
        	2.如果key相同,会把前面的值替换掉,但是必须是同一个对象
     	3.HashMap是无序的
     	4.new出来的都不是相同的key,因为地址不同。如果属性一样,想替换前面对应属性一样的valus时候,需要重写equals&hashcode方法
    
     	*/
     	
     	Map<Student,String> map = new HashMap<Student,String>();
     	
     	map.put(new Student("小刘", 18), "湖北");
     	map.put(new Student("小胡", 18), "湖南");
    

    // Student stu = new Student(“小官”, 18);
    // map.put(stu, “广东”);
    // map.put(stu, “广西”);
    map.put(new Student(“小官”, 18), “广东”);
    map.put(new Student(“小官”, 18), “广西”);

     	//System.out.println("map:" + map);
     	//遍历
     	Set<Entry<Student, String>> entries = map.entrySet();
     	for(Entry<Student, String> entry : entries){
     		System.out.println(entry.getKey() + " --- " + entry.getValue());
     	}
     	
     	
     }
    

    }

    class Student{
    String name;
    int age;
    public Student(String name, int age) {
    super();
    this.name = name;
    this.age = age;
    }
    @Override
    public String toString() {
    return “Student [name=” + name + “, age=” + age + “]”;
    }
    @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;
    }
    @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;
    }
    }

01.LinkedHashMap

  • LinkedHashMap是存和取的顺序是一样
  • HashMap是存和取的顺序不是一样
  • LinkedHashMap它是继承HashMap

02.TreeMap

  • TreeMap会对键key进行排序

  • TreeMap的key,如果是自定义对象话,这个对象要实现Comparable接口,

  • 或者说在new TreeMap的时候,传一个comparator参数

      03.集合的嵌套例子,Map嵌套Set
         		1.创建两个班(Set)
         		Set<Student> javaClass = new HashSet<Student>();
         		javaClass.add(new Student("小贾", 28));
         		javaClass.add(new Student("小牛", 18));
         		
         		Set<Student> h5Class =   new HashSet<Student>();
     		h5Class.add(new Student("小丽", 28));
     		h5Class.add(new Student("小红", 18));
     		
     		//2.创建一个学校(Map)
     		//Key:班级名字,Value:这个班所有学生
     		
     		/***
     		 * HashMap嵌套HashSet,或者说Map里嵌套Set
     		 */
     		Map<String,Set<Student>> school = new HashMap<String,Set<Student>>();
     	school.put("Java班级", javaClass);
     	school.put("H5班级", h5Class);
     	
     	//3.遍历
     	//3.1遍历学校里的班级
     	for(Entry<String,Set<Student>> entry : school.entrySet()){
     		System.out.println("班级名称:" + entry.getKey());
     		
     		//3.2 遍历班级里学生
     		//Set<Student> myClass = entry.getValue();
     		for(Student stu : entry.getValue()){
     			System.out.println(stu);
     		}
     	}
    

04.面试题:HashMap和Hashtable区别
/* 1.Hashtable是JDK1.0版本出现的,是线程安全的,效率低,有加锁[很少用]
* 2.HashMap是JDK1.2版本出现的,是线程不安全的,效率高
3.Hashtable不可以存储null键和null值
4.HashMap可以存储null键和null值*/

05.Collections集合工具类
Collections成员方法
public static void sort(List list) 排序
public static int binarySearch(List<?> list,T key) 二分查找
public static T max(Collection<?> coll) 取大值
public static void reverse(List<?> list) 反转
public static void shuffle(List<?> list) 打乱顺序
06.泛型固定下边界 【? super E】
/*泛型固定下边界 ? super E

1.【? extends E】-表示泛型固定上边界
? 表示子类,E表示父类
ArrayList.addAll(Collection<? extends Person> c)

2.【? super E】 -表示泛型固定下边界
? 表示父类,E表示的是子类
ArrayList.sort(Comparator<? super Student> c)

3.【? extends E 】针对存的操作
4.【? super E】 针对取的操作*/

发布了30 篇原创文章 · 获赞 21 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44078196/article/details/86533509
今日推荐