——- android培训、java培训、期待与您交流! ———-
集合:
集合的由来: 由于数组满足不了变化的需求,那么java就给我们提供了一个容器就是集合
集合和数组的区别:
a: 长度的区别: 集合的长度是可变的数组的长度是不可变
b: 存储数据类型的区别: 数组可以存储基本数据类型也可以存储引用数据类型,而集合只能存储引用数据利息
c: 内容的区别: 数组只能存储同一种数据类型的元素,而集合可以存储多种数据类型的元素
集合的功能方法:
boolean add(E e) 添加元素
boolean remove(Object o) 删除元素
void clear() 移除所有的元素
boolean contains(Object o) 判断是否包含指定的元素
boolean isEmpty() 判断集合是否为空
int size() 获取集合的长度
boolean addAll(Collection c) 添加一个集合的元素
boolean removeAll(Collection c) 移除一个集合的元素 , 移除一个以上算是移除
boolean containsAll(Collection c) 判断是否包含一个集合的元素 , 包含所有的才算是包含
boolean retainAll(Collection c) 获取交集 , A集合对B集合取交集,交集元素去A中了,返回的boolean类型的值表示的意思是集合A是否发生改变
Object[] toArray(): 把集合转换成数组
Iterator<E> iterator(): (重点)
遍历:
Collection col = new ArrayList() ;
col.add("刘亦菲") ;
col.add("范冰冰") ;
col.add("李冰冰") ;
Iterator it = col.iterator() ;
while(it.hasNext()) { // 判断是否存在下一个元素
// 获取元素
String s = (String)it.next() ; // next()方法的注意事项: 获取元素以后并将指针移向下一个位置
// 输出
System.out.println(s + "----" + s.length());
}
List 特点: 元素有序 , 元素可以重复 , 每一个元素都有对应的索引
void add(int index,E element): 在指定的索引处添加元素
E remove(int index): 删除指定索引处的元素
E get(int index): 获取指定索引处的元素
E set(int index,E element): 给指定索引处的元素赋值
使用for循环进行遍历:
<pre name="code" class="java"> List list = new ArrayList() ;
list.add("邓超") ;
list.add("黄晓明") ;
list.add("刘德华") ;
for(int x = 0 ; x < list.size() ; x++){
// 获取元素
String s = (String)list.get(x) ;
// 输出
System.out.println(s + "----" + s.length());
}
ListIterator : 列表迭代器 (了解) boolean hasPrevious(): 判断是否存在前一个元素 E previous(): 获取前一个元素 ListIterator 可以完成反向遍历 , 但是要完成反向遍历需要先进行正向遍历 , 所以说意义不大 ConcurrentModificationException: 并发修改异常 产生原因: 是使用迭代器进行遍历的时候使用集合修改元素,而这时候迭代器并不知道 解决方案: a: 使用迭代器进行遍历的时候使用迭代器进行修改元素(ListIterator) b: 使用集合遍历,集合自身修改元素(一般使用的是for循环) 数据结构 分类: 栈 , 队列 , 数组 , 链表 , 树 , 哈希表 栈的特点: 先进后出 队列的特点: 先进先出 数组的特点: 查询快,增删慢 链表的特点: 查询慢,增删快 ArrayList : 底层的数据结构是数组 , 查询快 , 增删慢 , 线程不安全, 效率高 Vector : 底层的数据结构是数组 , 查询快 , 增删慢 , 线程是安全的 , 效率低 特有的功能: public void addElement(E obj): 添加元素 public E elementAt(int index) 获取指定索引处的元素 public Enumeration elements() 可以遍历集合 Vector 集合使用特有的方法进行遍历:
Vector vector = new Vector() ;
vector.addElement("张三") ;
vector.addElement("李四") ;
vector.addElement("王五") ;
Enumeration en = vector.elements() ;
while(en.hasMoreElements()) { // 判断是否有下一个元素
// 获取元素
String s = (String)en.nextElement() ; // 获取元素
// 输出
System.out.println(s + "---" + s.length());
}
LinkedList : 底层的数据结构是链表 , 查询慢 , 增删快 , 线程不安全,效率高
特有的功能:
public void addFirst(E e) 在第一个位置添加元素
public void addLast(E e) 在最有一个位置添加元素
public E getFirst() 获取第一个元素
public E getLast() 获取最后一个元素
public E removeFirst() 删除第一个元素 , 并返回被移除的元素
public E removeLast() 删除最后一个元素 , 并返回被移除的元素
请用LinkedList模拟栈数据结构的集合,并测试 ?
class MyLinkedList {
private LinkedList list ;
public MyLinkedList() {
list = new LinkedList() ;
}
public String get() {
return list.removeFirst() ;
}
public void add(Object obj) {
list.addFirst(obj) ;
}
public boolean isEmpty() {
return list.isEmpty() ;
}
}
public class Test {
public static void main(String[] args) {
MyLinkedList ml = new MyLinkedList();
ml.add("hallo");
ml.add("word");
ml.add("java");
ml.add("javaee");
while(!ml.isEmpty()){
System.out.println(ml.get());
}
}
}
泛型(Generic) :
泛型的概述: 是一种把类型的明确推迟到创建对象获取调用方法的时候的一种特殊的类型 ; 属于参数化类型: 就是可以把这个类型作为参数进行传递
泛型的格式:
<数据类型>
数据类型: 只能是引用数据类型
泛型的好处:
a: 把运行期的错误提前到了编译期
b: 省去了强制类型转换
c: 去掉了黄色警告线
泛型的由来:
在早期的时候我们如果想接收任意的类型,那么我们使用的是Object, 然后使用Object在做向下转型的时候,可能会存在一定的安全问题,于是
java自1.5以后就给我们提供了泛型.
泛型的应用:
a: 泛型类: 就是把泛型定义在类上
格式: public class 类名 <数据类型> {}
b: 泛型方法: 就是把泛型定义在方法上
格式: 修饰符 <数据类型> 返回值类型 方法名(数据类型 变量名) {}
c: 泛型接口: 就是把泛型定义在接口上
格式: public interface 接口名<数据类型> {}
泛型接口的子类:
a: 在定义子类的时候已经可以明确到底是什么类型
b: 在定义字了的时候还不知道是什么类型,那么这个子类就需要定义成泛型类
泛型的注意事项:
泛型只是针对编译期有效,到了运行期以后进行泛型擦除.
泛型的通配符:
? : 表示任意的类型
? extends E : 向下限定, 表示的是E或者E的子类
? super E : 向上限定, 表示的是E或者E的父类
增强for :
出现的原因: 是为了简化数组和集合的遍历
格式:
for(元素的数据类型 变量名 : 数组或者集合名) {
这个地方直接使用变量名,那么这个变量其实就是对一个的元素.
}
举例:
int[] arr = {23, 45, 67 , 78} ;
// 使用增强for遍历
for(int a : arr ) {
System.out.println(a) ;
}
静态导入:
格式: import static 包名...类名.方法名 ;
注意事项: 如果一个类中存在了和静态导入的方法名相同的方法,那么这个时候就需要明确到底使用的是哪个方法 .
可变参数:
格式: 修饰符 返回值类型 方法名(数据类型... 变量名) {}
可变参数的本质: 是一个数组
举例
public int add(int... a) {
int sum = 0 ;
for(int x : a ) {
sum += x ;
}
return sum ;
}
Set: 集合 元素无序 , 但是可以保证元素的一个唯一性
HashSet: 底层的数据结构是哈希表(是一种元素是链表的数组,集成了数组和链表的优点)
底层主要依赖于两个方法一个是hashCode()一个是equals()方法 ; 不同的对象它的哈希码值不同.而哈希码值相同的时候不一定就是同一个对象
所以在看源代码的时候,是首先是判断哈希码值是否相等,如果相等在调用equals方法判断指定的内容是否相等.
举例:
import java.util.HashSet;
/**
* 需求:使用HashSet集合存储自定义对象,保证元素的唯一性
*
* Student name , age
* 我们认为name和age都是相同的时候,我们认为是同一个对象
*
* 结论: 在以后使用HashSet存储自定义对象的时候,要保证元素的为一性,我们应该重写hashCode和equals方法
*
*/
public class HashSetDemo {
public static void main(String[] args) {
// 创建集合对象
HashSet<Student> hashSet = new HashSet<Student>() ;
// 创建自定义对象
Student s1 = new Student("刘亦菲" , 23) ;
Student s2 = new Student("范冰冰" , 32) ;
Student s3 = new Student("李冰冰" , 35) ;
Student s4 = new Student("刘亦菲" , 23) ;
Student s5 = new Student("刘亦菲" , 18) ;
Student s6 = new Student("李冰冰" , 35) ;
// 把元素添加到集合中
hashSet.add(s1) ;
hashSet.add(s2) ;
hashSet.add(s3) ;
hashSet.add(s4) ;
hashSet.add(s5) ;
hashSet.add(s6) ;
// 遍历
for(Student s : hashSet) {
// 输出
System.out.println(s.getName() + "----" + s.getAge());
}
}
}
public class Student {
private String name ;
private int age ;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
/**
* 引用数据类型调用hashCode方法获取哈希值 + 基本数据类型的值 * 非0,1的整数
*
* Student s1 : name "张三" 22 , age 23
* Student s2 : name "李四" 23 , age 22
*
*/
return this.name.hashCode() + age * 14 ;
}
@Override
public boolean equals(Object obj) {
System.out.println(this + "----" + obj);
// 提高效率
if(this == obj) {
return true ;
}
// 提高程序的安全性
if(!(obj instanceof Student)) { // obj 是否是Student的一个实例
/**
* instanceof: 判断指定的一个对象是否是另一个类的一个实例
*/
return false ;
}
// 向下转型
Student s = (Student)obj ;
return this.name.equals(s.getName()) && this.age == s.getAge() ;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
LinkedHashSet: 底层的数据结构是链表和哈希表,元素有序 ,并且唯一
元素的有序靠的是链表实现
元素的唯一靠的是哈希表实现
举例:
import java.util.LinkedHashSet;
/**
* LinkedHashSet: 底层的数据结构是链表和哈希表
* 特点: 元素有序 , 并且元素唯一
* 有序是靠链表保证
* 唯一是靠哈希表保证
*/
public class LinkedHashSetDemo {
public static void main(String[] args) {
// 创建对象
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>() ;
// 添加元素
linkedHashSet.add("hello") ;
linkedHashSet.add("world") ;
linkedHashSet.add("java") ;
linkedHashSet.add("java") ;
// 遍历
for(String s : linkedHashSet) {
System.out.println(s);
}
}
}
TreeSet :
TreeSet 集合可以对元素进行排序,而这种排序又被分为两种方式,第一种方式是自然排序,第二种是比较器排序
那么我们到底使用的是那种排序主要依赖于构造方法
构造方法:
public TreeSet() : 使用的是自然排序
如果使用的是自然排序,那么就对元素是有要求的,要求这个元素必须去实现Comparable接口,并重写compareTo方法
如果没有实现这个接口会报错(ClassCastException) ;
public TreeSet(Comparator comp) : 使用的是比较器进行排序
实现有两种方式:
第一种: 可以定义一个类,然后让这个类去实现Comparator接口,然后重写compare方法
第二种: 直接使用匿名内部类实现
举例
public TreeSet() : 使用的是自然排序
import java.util.TreeSet;
/**
* 使用TreeSet集合存在自定义对象,按照年龄进行排序
* 我们是明确主要条件,但是同时我们自己要分析次要条件
*/
public class TreeSetTest {
public static void main(String[] args) {
// 创建对象
TreeSet<Student> treeSet = new TreeSet<Student>() ; // 使用的自然排序
// 创建自定义对象
Student s1 = new Student("刘亦菲" , 23) ;
Student s2 = new Student("李冰冰" , 35) ;
Student s3 = new Student("范冰冰" , 30) ;
Student s4 = new Student("成龙" , 18) ;
Student s5 = new Student("李连杰" , 15) ;
Student s6 = new Student("李世民" , 15) ;
// 把自定义对象添加到集合中
treeSet.add(s1) ;
treeSet.add(s2) ;
treeSet.add(s3) ;
treeSet.add(s4) ;
treeSet.add(s5) ;
treeSet.add(s6) ;
// 遍历
for(Student s : treeSet) {
// 输出
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
//学生类实现Comparable接口
public class Student implements Comparable<Student>{
private String name ;
private int age ;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student o) {
// 比较完年龄以后,如果返回的是0,也不能说明是同一个对象,那么我们还需要比较姓名
int num = this.age - o.getAge() ;
// 比较姓名
int num2 = (num == 0 )? this.name.compareTo(o.getName()) : num ;
return num2 ;
}
}
public TreeSet(Comparator comp) : 使用的是比较器进行排序
第一种: 可以定义一个类,然后让这个类去实现Comparator接口,然后重写compare方法
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet使用比较器进行排序
* public TreeSet(Comparator<? super E> comparator):
* 集合存在自定义对象,按照年龄进行排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
// 创建对象
// TreeSet<Student> treeSet = new TreeSet<Student>(new MyComparator()) ;
TreeSet<Student> treeSet = new TreeSet<Student>( new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 比较年龄
int num = s1.getAge() - s2.getAge() ;
// 比较姓名
int num2 = (num == 0) ? s1.getName().compareTo(s2.getName()) : num ;
return num2;
}
}) ;
// 创建自定义对象
Student s1 = new Student("刘亦菲" , 23) ;
Student s2 = new Student("李冰冰" , 35) ;
Student s3 = new Student("范冰冰" , 30) ;
Student s4 = new Student("成龙" , 18) ;
Student s5 = new Student("李连杰" , 15) ;
Student s6 = new Student("李世民" , 15) ;
// 把自定义对象添加到集合中
treeSet.add(s1) ;
treeSet.add(s2) ;
treeSet.add(s3) ;
treeSet.add(s4) ;
treeSet.add(s5) ;
treeSet.add(s6) ;
// 遍历
for(Student s : treeSet) {
// 输出
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
//学生类
public class Student {
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//自定义一个类去实现接口Comparator
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// 比较年龄
int num = s1.getAge() - s2.getAge() ;
// 比较姓名
int num2 = (num == 0) ? s1.getName().compareTo(s2.getName()) : num ;
return num2;
}
}
public TreeSet(Comparator comp) : 使用的是比较器进行排序
第二种: 直接使用匿名内部类实现
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/**
* 需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
*/
public class TreeSetTest {
public static void main(String[] args) {
// 创建对象
TreeSet<Student> treeSet = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 按照总分从高到低输出到控制台。
int num = s2.getTotal() - s1.getTotal() ;
// 比较语文成绩
int num2 = (num == 0) ? s2.getChineseScore() - s1.getChineseScore() : num ;
// 比较数学成绩
int num3 = (num2 == 0 )? s2.getMathScore() - s1.getMathScore() : num2 ;
// 比较英语成绩
int num4 = (num3 == 0) ? s2.getEnglishScore() - s1.getEnglishScore() : num3 ;
// 比较姓名
int num5 = (num4 == 0) ? s2.getName().compareTo(s1.getName()) : num4 ;
return num5;
}
}) ;
// 键盘录入学生信息
for(int x = 0 ; x < 3 ; x++) {
Scanner sc = new Scanner(System.in) ; // 创建Scanner对象
System.out.println("请您输入姓名: ");
String userName = sc.nextLine() ;
System.out.println("请您输入语文成绩:" );
String chineseScoreStr = sc.nextLine() ;
System.out.println("请您输入数学成绩:" );
String mathScoreStr = sc.nextLine() ;
System.out.println("请您输入英语成绩:" );
String englishScoreStr = sc.nextLine() ;
// 把数据封装成一个学生对象
Student s = new Student() ;
s.setName(userName) ;
s.setChineseScore(Integer.parseInt(chineseScoreStr)) ;
s.setMathScore(Integer.parseInt(mathScoreStr)) ;
s.setEnglishScore(Integer.parseInt(englishScoreStr)) ;
// 把学生对象添加到集合中
treeSet.add(s) ;
}
System.out.println("学生信息录入完毕........");
// 遍历
System.out.println("姓名\t\t总分\t\t语文成绩\t\t数学成绩\t\t英语成绩");
for(Student s : treeSet) {
System.out.println(s.getName() + "\t\t" + s.getTotal() + "\t\t" + s.getChineseScore() + "\t\t" + s.getMathScore() + "\t\t" + s.getEnglishScore());
}
}
}
public class Student {
private String name ;
private int chineseScore ;
private int mathScore ;
private int englishScore ;
public Student() {
super();
}
public Student(String name, int chineseScore, int mathScore, int englishScore) {
super();
this.name = name;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
this.englishScore = englishScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChineseScore() {
return chineseScore;
}
public void setChineseScore(int chineseScore) {
this.chineseScore = chineseScore;
}
public int getMathScore() {
return mathScore;
}
public void setMathScore(int mathScore) {
this.mathScore = mathScore;
}
public int getEnglishScore() {
return englishScore;
}
public void setEnglishScore(int englishScore) {
this.englishScore = englishScore;
}
public int getTotal() {
return this.chineseScore + this.mathScore + this.englishScore ;
}
}