------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
集合的继承体系结构图:
Collection
|- List
|- ArrayList
|- LinkedList
|- Vector
|- Set
|- HashSet
|- TreeSet
Collection: 集合的顶层接口
方法:
添加功能:
boolean add(E e) 把给定的数据 添加到集合中
boolean addAll(Collection c) 把给定的集合的元素,添加到当前集合中
删除功能:
void clear() : 将集合中的元素清空
boolean remove(Object o): 将给定的元素在集合中删除
boolean removeAll(Collection c)将给定的集合元素,在当前集合中删除
长度功能:
int size() 返回集合中元素的个数
转换功能:
Object[] toArray(): 把集合 转换成数组
判断功能:
boolean contains(Object o)判断当前集合中是否包含给定的元素
boolean isEmpty() 判断当前集合中的元素 是否为空
boolean containsAll(Collection<?> c) 判断当前集合中,是否包含给定集合中所有的元素
遍历功能(迭代器):
Iterator<E> iterator(): 遍历集合中的元素
Iterator中的方法:
boolean hasNext()如果仍有元素可以迭代,则返回 true。
Object next() 返回迭代的下一个元素。
交集功能:
boolean retainAll(Collection<?> c)判断两个集合中相同的元素
List:
特点:
它是Collection子集合
可以存储重复的元素
有序(元素存与取顺序一致)
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_05_List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
* 使用List集合存储自定义对象,并遍历
*/
public class ListDemo2 {
public static void main(String[] args) {
//创建List集合对象
List list = new ArrayList();
//创建元素对象
Person p1 = new Person("天花", 10);
Person p2 = new Person("菊花", 11);
Person p3 = new Person("桃花", 12);
//添加元素到集合
list.add(p1);
list.add(p2);
list.add(p3);
//遍历
Iterator it = list.iterator();
while (it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName() + "--" + p.getAge());
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><pre class="java" name="code">package cn.itcast_03_ArrayList;
public class Person {
private String name;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_12_ForEach;
import java.util.ArrayList;
/*
* 需求:请使用ArrayList集合存储多个自定义对象,并遍历(泛型, 增强for)
*/
public class ForEachTest2 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("赵日天"));
list.add(new Person("啦啦"));
list.add(new Person("哈哈"));
for(Person p : list) {
System.out.println(p.getName());
}
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> </span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> </span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> </span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><p>List:
特有方法:
void add(int index, E element) : 在当前集合中指定位置 添加给定的元素
Object get(int index) 返回集合中指定位置的元素。
int indexOf(Object o)返回此集合中第一次出现的指定元素的索引;如果此集合不包含该元素,则返回 -1。
E remove(int index)移除集合中指定位置的元素
E set(int index, E element)用指定元素替换集合中指定位置的元素
ListIterator<E> listIterator() 返回此集合元素的列表迭代器</p><p> 并发修改异常产生的原因及解决方案:
ConcurrentModificationException 并发修改异常:
在使用迭代器遍历的过程中,原有集合中的元素个数不能发生改变,否则抛出 并发修改异常
解决方式:
普通for:
添加的新元素到原有集合的末尾添加
ListIterator:
添加的新元素在Java元素的后面添加
常见的数据结构:
栈:
特点:
先进后出
队列:
特点:
先进先出
数组:
特点:
增删慢,查询快
链表:
特点:
增删快,查找慢
List的三个子类的特点:
ArrayList:
底层: 数组结构, 增删慢 ,查询快
线程不同步,效率高,不安全
Vector:
底层: 数组结构, 增删慢,查询快
线程同步,效率低, 安全
LinkedList:
底层: 链表结构, 增删快,查询慢
线程不同步,效率高,不安全 </p><p>
ArrayList:
案例:
ArrayList存储字符串并遍历
</p><pre class="java" name="code">public class ArrayListDemo {
public static void main(String[] args) {
//创建集合对象
ArrayList list = new ArrayList();
//添加字符串元素到集合
list.add("Hello");
list.add("Java");
list.add("hehe");
//遍历
for (int i =0; i<list.size(); i++) {
//获取到每一个元素,打印
System.out.println( list.get(i) );
}
}
}</span></span></span>
Vector:
特有方法:
public void addElement(Object obj) 添加元素到集合 ———— add(Obejct obj)
public Object elementAt(int index) 返回集合中给定位置上的元素 ---- get(int index)
public Enumeration elements()返回此向量的组件的枚举 --- iterator()
boolean hasMoreElements() ---- hasNext()
Object nextElement() --- next();
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">public class VectorDemo {
public static void main(String[] args) {
//创建集合对象
Vector v = new Vector();
//添加元素到集合
//v.add("hello");
v.addElement("hello");
v.addElement("world");
//遍历
//size() 与 get()
for (int i = 0; i < v.size(); i++) {
System.out.println( v.elementAt(i) );
}
//迭代器
Enumeration en = v.elements();
//判断是否有下一个元素
while (en.hasMoreElements()) {
//获取下一个元素
System.out.println( en.nextElement() );
}
}
}
</span></span></span>
LinkedList:
特有方法:
public void addFirst(Object e)将指定元素插入此列表的开头
public void addLast(Object e)将指定元素添加到此列表的结尾。
public Object getFirst()返回此列表的第一个元素
public Object getLast()返回此列表的最后一个元素。
public Object removeFirst()移除并返回此列表的第一个元素。
public Object removeLast()移除并返回此列表的最后一个元素。
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">public class LinkedListDemo {
public static void main(String[] args) {
//创建集合对象
LinkedList list = new LinkedList();
//添加元素
list.add("JavaSE");
//public void addFirst(Object e)
list.addFirst("JavaEE");
//public void addLast(Object e)
list.addLast("Android");
//public Object getFirst()
System.out.println("getFirst:"+ list.getFirst());
//public Object getLast()
System.out.println("getLast:"+ list.getLast());
System.out.println("-------------------------");
//public Object removeFirst()
//Object obj = list.removeFirst();
//System.out.println("obj:"+obj);
//public Object removeLast()
Object obj = list.removeLast();
System.out.println("obj:"+obj);
//显示
System.out.println(list);
}
}
</span></span></span>
泛型:
泛型: Generic
泛型的格式:
< 泛型类型 >
注意: 这里的泛型类型可以任意的内容,基本的数据类型,
比如 String Person QQ、T、E、K
泛型常见在哪里可以使用?
接口上使用泛型
类上使用泛型
方法上使用泛型
泛型类:
把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
<QQ> 定义一个泛型
QQ 使用当前这个泛型,这个QQ在程序运行的时候,会对应着一个具体的数据类型
例如:
public class Test<QQ> {
private QQ name;
public void setName(QQ name){
this.name = name;
}
public QQ getName(){
return name;
}
}
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">public class QQTest {
public static void main(String[] args) {
//Test t = new Test();
Test<String> t = new Test<String>();
t.setName("哈哈");
System.out.println( t.getName() );
Test<Integer> t2 = new Test<Integer>();
t2.setName(123);
System.out.println( t2.getName() );
}
}
</span></span></span>
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
K 的类型是在创建对象的时候 确定的
TT 类型是在调用方法的时候 确定的
这里的K,TT 理解为 是一种数据类型的变量名
注意:创建多个泛型类对象的时候,可以赋值不同的泛型类型,不会产生冲突
例如:
public class GenericMethod<K> {
//普通方法
public String method(String str){
return str + "哈哈";
}
//泛型方法
public K function(K str){
return str;
}
//泛型方法
public <TT> TT show(TT str) {
return str;
}
}
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
例如
public interface Inter<TT> {
public TT show(TT str);
}
实现泛型接口的类:
方式1:在编写类的时候实现泛型接口
public class InterImpl implements Inter<String> {
@Override
public String show(String str) {
return str;
}
}
方式2:创建对象的时候,确定泛型的数据类型
InterImpl<QQ> 声明泛型QQ
implements Inter<QQ> 使用QQ 所代表的数据类型
public class InterImpl<QQ> implements Inter<QQ>{
@Override
public QQ show(QQ str) {
return str;
}
}
泛型高级之通配符
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向上限定,E及其子类
?代表了 可以是E所对应的数据类型,或者是E的子类类型
例如:
? extends Animal
? 代表了 Animal类型,或者Animal子类类型
? super E
向下限定,E及其父类
?代表了 可以使 E所对应的数据类型,或者是E的父类类型
例如:
? super Dog
? 代表的是 Dog类型,或者是Dog的父类类型
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><pre class="java" name="code">package cn.itcast_11_Generic;
import java.util.ArrayList;
import java.util.Collection;
/*
* 泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向上限定,E及其子类
?代表了 可以是E所对应的数据类型,或者是E的子类类型
例如:
? extends Animal
? 代表了 Animal类型,或者Animal子类类型
? super E
向下限定,E及其父类
?代表了 可以使 E所对应的数据类型,或者是E的父类类型
例如:
? super Dog
? 代表的是 Dog类型,或者是Dog的父类类型
*/
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
public class CollectionDemo {
public static void main(String[] args) {
//泛型的数据类型 要求左右一致
//Collection<Object> coll = new ArrayList<Animal>();
//Collection<Animal> coll = new ArrayList<Dog>();
Collection<?> c1 = new ArrayList<Animal>();
Collection<?> c2 = new ArrayList<Dog>();
Collection<?> c3 = new ArrayList<Cat>();
Collection<?> c4 = new ArrayList<Object>();
Collection<? extends Animal> c5 = new ArrayList<Animal>();
Collection<? extends Animal> c6 = new ArrayList<Dog>();
Collection<? extends Animal> c7 = new ArrayList<Cat>();
// Collection<? extends Animal> c8 = new ArrayList<Object>(); 因为 Object类型,不是Animal类型或Animal的子类型
Collection<? super Animal> c9 = new ArrayList<Animal>();
// Collection<? super Animal> c10 = new ArrayList<Dog>();// 因为Dog 不是 Animal类型 或者 Animal的父类型
// Collection<? super Animal> c11 = new ArrayList<Cat>();// 因为Cat 不是 Animal类型 或者 Animal的父类型
Collection<? super Animal> c12 = new ArrayList<Object>();
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"></span> </span></span>
增强for的概述和使用:
增强for概述 jdk1.5出现的新特性
简化数组和Collection集合的遍历
格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
好处:简化遍历
注意事项:增强for的目标要判断是否为null
把前面的集合代码的遍历用增强for改进
注意:
如果需要使用索引, 请使用传统for
如果不需要使用索引,推荐是使用增强for(), 也可以使用迭代器
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><pre class="java" name="code">package cn.itcast_12_ForEach;
import java.util.ArrayList;
/*
* 需求:请使用ArrayList集合存储多个自定义对象,并遍历(泛型, 增强for)
*/
public class ForEachTest2 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("赵日天"));
list.add(new Person("啦啦"));
list.add(new Person("哈哈"));
for(Person p : list) {
System.out.println(p.getName());
}
}
}
</span></span></span>
(了解)静态导入:
静态导入概述
格式:import static 包名….类名.方法名;
可以直接导入到方法的级别
注意事项
方法必须是静态的
(了解)可变参数
变参数概述
定义方法的时候不知道该定义多少个参数
格式
修饰符 返回值类型 方法名(数据类型… 变量名){}
注意:
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,
那么,可变参数肯定是最后一个,并且一个方法中只能有一个可变参数
(了解)Set:一个不包含重复元素的集合
(重点)HashSet:
底层: 哈希表结构
特点:
不包含重复元素
无序(元素的存与取的顺序不一致)
线程不同步--不安全--效率高
(重点)HashSet如何保证元素唯一性:
重写 hashCode()方法 与 equals()方法
(了解)LinkedHashSet:
底层:哈希表结构 + 链表结构
特点:
不包含重复元素
由链表保证元素有序
由哈希表保证元素唯一
线程不同步--不安全--效率高
(了解)TreeSet:
底层:二叉树结构(红黑树结构)
线程不同步--不安全--效率高
TreeSet是如何保证元素的排序和唯一性的:
1: 元素对应的类,实现自然排序接口[Comparable],重写compareTo(obj1)方法
2: 或创建TreeSet集合对象时,实现比较器接口[Comparator], 重写compare(obj1, obj2)方法
(注意)Collection集合总结:
Collection
|- List
|- ArrayList(重点)
|- Vector (了解)
|- LinkedList (了解)
|- Set
|- HashSet (重点)
|- TreeSet(了解)
以后对于Collection集合,掌握如下:
考虑元素唯一 使用HashSet
可以有重复元素 使用ArrayList
案例:
ArrayList集合 嵌套 ArrayList集合
HashSet集合存储自定义对象并遍历
TreeSet集合存储自定义对象并遍历
编写一个程序,获取10个1至20的随机数,要求随机数不能重复
键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
(了解)静态导入: 静态导入概述 格式:import static 包名….类名.方法名; 可以直接导入到方法的级别 注意事项 方法必须是静态的
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_01_StaticImport;
/*
* 静态导入
* import static 包名….类名.方法名;
可以直接导入到方法的级别
*/
import static java.lang.Math.abs;
public class StaticImportDemo {
public static void main(String[] args) {
System.out.println(Math.abs(-3.14));
System.out.println(abs(-3.5));
}
}
</span></span></span>
(了解)可变参数
变参数概述
定义方法的时候不知道该定义多少个参数
格式
修饰符 返回值类型 方法名(数据类型… 变量名){}
注意:
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,
那么,可变参数肯定是最后一个,并且一个方法中只能有一个可变参数
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_02_Args;
import java.util.Arrays;
import java.util.List;
/*
* Arrays数组工具类中方法
* public static <T> List<T> asList(T... a) 可以把多个参数中的数据,存储到List集合中
*
* 用法:
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
*/
public class AsListDemo {
public static void main(String[] args) {
//这种用法常见
List<String> list = Arrays.asList("Java", "Hello","JavaEE");
System.out.println(list);
//不常见
String[] arr = {"aaa","bbb","ccc"};
List<String> list2 = Arrays.asList(arr);
System.out.println(list2);
}
}
</span></span></span>
Set:一个不包含重复元素的集合
HashSet:
底层: 哈希表结构
特点:
不包含重复元素
无序(元素的存与取的顺序不一致)
线程不同步--不安全--效率高
HashSet如何保证元素唯一性:
重写 hashCode()方法 与 equals()方法
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_05_HashSet;
public class Person {
private String name;
private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(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 String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*
@Override
public int hashCode() {
return 0;
}
*/
@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;
Person other = (Person) 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;
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><pre class="java" name="code">package cn.itcast_05_HashSet;
import java.util.HashSet;
/*
* 案例: 使用HashSet集合存储自定义对象 并遍历
*
* 通过查找源代码得知: HashSet集合中的add方法,底层会调用 hashCode() 与 equals()方法
*
* 由于 String类中 覆盖了Object类中的hashCode() 与 equals()方法 ,所以可以保证元素的唯一
*
* 我们可以通过重写 Object类中的hashCode() 与 equals()方法, 来保证HashSet集合中元素的唯一性
* 注意: 自定义类Person 中, 重写 hashCode() 与 equals()方法
*
*/
public class HashSetDemo2 {
public static void main(String[] args) {
//创建HashSet集合
HashSet<Person> set = new HashSet<Person>();
//创建Person元素对象
Person p1 = new Person("周瑜", 28);
Person p2 = new Person("诸葛亮", 30);
Person p3 = new Person("郭嘉", 33);
Person p4 = new Person("周瑜", 28);
//添加到集合
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
//遍历
for (Person p : set) {
System.out.println(p.getName() + "--" +p.getAge());
}
}
}
</span></span></span>
LinkedHashSet: 底层:哈希表结构 + 链表结构 特点: 不包含重复元素 由链表保证元素有序 由哈希表保证元素唯一 线程不同步--不安全--效率高
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_07_LinkedHashSet;
import java.util.LinkedHashSet;
/*
* LinkedHashSet:
* 它是HashSet的子类
* 有序(元素存与取顺序一致)
* 底层存储: 哈希表结构 加上 链表结构
* 通过哈希表结构 保证LinkedHashSet元素唯一
* 通过 链表结构 保证元素有序
* 线程不同步--不安全-- 效率高
*/
public class LinkedHashSetDemo {
public static void main(String[] args) {
//创建集合对象
LinkedHashSet<String> set = new LinkedHashSet<String>();
//添加元素
set.add("大湿兄");
set.add("二师兄");
set.add("小师妹");
set.add("小师妹");
//遍历
for (String s : set) {
System.out.println(s);
}
}
}</span></span></span>
(了解)TreeSet:
底层:二叉树结构(红黑树结构)
线程不同步--不安全--效率高
TreeSet是如何保证元素的排序和唯一性的:
1: 元素对应的类,实现自然排序接口[Comparable],重写compareTo(obj1)方法
2: 或创建TreeSet集合对象时,实现比较器接口[Comparator], 重写compare(obj1, obj2)方法
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_08_TreeSet;
import java.util.TreeSet;
/*
* TreeSet:
* 底层结果:二叉树结构
* 保证元素的唯一与元素进行排序
* TreeSet集合对元素的排序提供两种方式
* a: 自然排序 接口 Comparable<T>
* b: 比较器排序 接口 Comparator<T>
*
* 通过compareTo()方法为0,来保证元素的唯一性
* 通过compareTo()方法不为0,来进行大小排序
*
* 用TreeSet存储Integer类型数据进行排序和唯一。
20,18,23,22,17,24,19,18,24
*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建TreeSet集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
//添加Integer元素到集合
ts.add(20);
ts.add(18);
ts.add(23);
ts.add(22);
ts.add(17);
ts.add(24);
ts.add(19);
ts.add(18);
ts.add(24);
//TreeMap
//遍历
//for (Integer in : ts) {
for (int in : ts) {
System.out.println(in);
}</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> }</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">}</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_08_TreeSet;
//实现自然排序接口 Comparable, 重写 compareTo()方法
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(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(Person p) {
//return 0;
//return -1;
//return 1;
//采用年龄进行比较
//this -- 代表着集合中的每一个对象
//Person p -- 代表着要参与比较的对象
//return this.getAge() - p.getAge();
//先判断年龄
int num = this.getAge() - p.getAge();
//再判断姓名
int result= (num == 0) ?( this.getName().compareTo(p.getName()) ): num;
return result;
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_08_TreeSet;
import java.util.TreeSet;
/*
* 案例: 使用TreeSet集合存储自定义对象,并遍历
*
* 分析:
* 1: 定义自定义类 Person
* ?? 没有重写 HashCode 和 equals方法
* 答: 当前集合是TreeSet集合,底层使用的是二叉树结构,所以不用重写 HashCode 和 equals方法
*
* 2:创建集合对象
* 3:创建元素对象
* 4:添加元素到集合
* 5:遍历
*
* java.lang.ClassCastException: cn.itcast_08_TreeSet.Person cannot be cast to java.lang.Comparable
*
* public interface Comparable<T>
* 此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
*
* 方法:
* int compareTo(T o)
* 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
*
* 字符串1.compareTo (字符串2) 小于0
* 字符串1小 , 字符串2大
*
* 字符串1.compareTo (字符串2) 等于0
* 字符串1和字符串2一样
*
* 字符串1.compareTo (字符串2) 大于0
* 字符串1大 , 字符串2小
*
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Person> ts = new TreeSet<Person>();
//3:创建元素对象
Person p1 = new Person("d大师兄",28);
Person p2 = new Person("d大师姐",18);
Person p3 = new Person("x小师姐",18);
Person p4 = new Person("x小师姐",18);
//4:添加元素到集合
ts.add(p1);
ts.add(p2);
ts.add(p3);
ts.add(p4);
//5:遍历
for (Person p : ts) {
System.out.println(p.getName() +"--"+ p.getAge());
}
}
}
</span></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_10_TreeSet_Test;
import java.util.Comparator;
import java.util.TreeSet;
/*
* TreeSet集合存储自定义对象并遍历
如果对象的成员变量值相同即为同一个对象
按照年龄进行从小到大进行排序
完成排序和元素的唯一: 有两个方式
1: 自然排序接口 Comparable, 实现 compareTo(o1) 方法
2: 比较器接口 Comparator, 实现 compare(o1, o2)方法//推荐
*/
public class TreeSetTest {
public static void main(String[] args) {
//1: 自然排序接口 Comparable, 实现 compareTo(o1) 方法
//创建集合对象
//TreeSet<Person> ts = new TreeSet<Person>();
//2: 比较器接口 Comparator, 实现 compare(o1, o2)方法
TreeSet<Person> ts = new TreeSet<Person>(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
System.out.println("12345");
//年龄
int num = p1.getAge() - p2.getAge();
//名字
int result = (num == 0) ? (p1.getName().compareTo(p2.getName())) : num ;
return result;
}
});
//添加元素到集合
ts.add(new Person("z张三", 18));
ts.add(new Person("w王五", 18));
ts.add(new Person("z赵六", 28));
ts.add(new Person("z赵六", 28));
ts.add(new Person("z赵六", 28));
//TreeMap
//遍历
for (Person p : ts) {
System.out.println(p.getName() + "--" + p.getAge());
}
}
}
</span></span></span>
Collection 集合 与 Map集合的区别?
Collection:
单个元素:光棍
Collection中的Set集合中,元素唯一
Map:
成对元素:夫妻,通常叫做 键值对
Map集合中的键唯一, 值可以重复
Map :
存储的是成对出现的元素
特点:
有键与值 组成是双列集合
键唯一, 值可以重复
Map集合的数据结构值针对键有效,跟值无关
方法:
V put(K key,V value) 添加键值对元素到集合
V remove(Object key) 根据指定的键,在集合中删除对应的键值对元素,返回键对应的值
void clear() 清空集合
boolean containsKey(Object key) 判断集合中是否包含给定的键
boolean containsValue(Object value) 判断集合中是否包含给定的值
boolean isEmpty() 判断集合是否为空
int size() 获取集合中键值对元素的个数
V get(Object key) 根据给定的键,获取对应的值
Set<K> keySet() 获取集合中所有的键
Collection<V> values() 获取集合中所有的值
Set<Map.Entry<K,V>> entrySet() 获取集合中所有的键值对元素对象
Map集合的遍历方式
方式1:根据键找值
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_02_Map_print;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* 通过Map 存储 多个String类型的键值对元素,并遍历
* 键String, 值 String
*
* 遍历方式:
* 1: 键找值 通过指定的键,获取对应的值
* //a: 获取到Map集合中所有的键的Set集合
//b: 遍历键的集合,得到每一个键
//c: 通过当前的键,获取对应的值
*
*/
public class MapDemo {
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a: 获取到Map集合中所有的键的Set集合
Set<String> keys = map.keySet();
//b: 遍历键的集合,得到每一个键
for (String key : keys) {
//c: 通过当前的键,获取对应的值
String value = map.get(key);
//显示
System.out.println( key +"--" + value );
}
}
}
</span></span>
方式2:根据键值对对象找键和值
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_02_Map_print;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* 通过Map 存储 多个String类型的键值对元素,并遍历
* 键String, 值 String
*
* 遍历方式:
* 1: 键找值
*
* 2: 通过键值对元素对象,找对应的键, 找对应的值 结婚证方式
* //a:获取所有键值对元素的Set集合
//b:遍历Set集合,得到每一个键值对元素对象
//c:通过键值对元素对象,获取键,获取值
*
* 方法:
* Set<Map.Entry<K,V>> entrySet(): 获得一个包含多个键值对元素的Set集合
*
* Map.Entry<K,V> 等价 结婚证<男的,女的>
* class 结婚证<男的,女的> {
* private 男的 man;
* private 女的 woman;
*
* public 男的 getMan(){
* return man;
* }
*
* public 女的 getWoman(){
* return woman;
* }
* }
*
* Set<Map.Entry<K,V>> entrySet = map.entrySet();
* Set< 结婚证<男的,女的>> entrySet = map.entrySet();
*
*/
public class MapDemo2 {
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a:获取所有键值对元素的Set集合
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//b:遍历Set集合,得到每一个键值对元素对象
for ( Map.Entry<String,String> entry : entrySet) {
//c:通过键值对元素对象,获取键,获取值
String key = entry.getKey();//获取键
String value = entry.getValue();//获取值
System.out.println(key +"--"+ value);
}
}
}
</span></span>
HashMap:
底层: 哈希表结构
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_03_HashMap;
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;
}
@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;
Person other = (Person) 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;
}
}
</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_03_HashMap;
import java.util.HashMap;
import java.util.Set;
/*
* HashMap集合键是String值是Student的案例
* 键是String
* 值是Student
*
* 底层的结构 只针对 键 有效, 与值无关
*/
public class HashMapDemo2 {
public static void main(String[] args) {
//创建集合对象
HashMap<String,Student> map = new HashMap<String,Student>();
//添加元素
Student s1 = new Student("周瑜", 28);
Student s2 = new Student("小乔", 18);
Student s3 = new Student("大乔", 19);
map.put("itcast001", s1);
map.put("itcast002", s2);
map.put("itcast003", s3);
map.put("itcast004", s1);
//遍历
//方式1 键找值
Set<String> keys = map.keySet();
//获取到每一个键
for (String key : keys) {
//通过当前的key, 获取对应的值 Student
Student s = map.get(key);
System.out.println(key +"---" + s.getName() +"---"+ s.getAge());
}
}
}
</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_03_HashMap;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/*
* HashMap:
* 底层: 哈希表结构
* 存储允许使用 null 值和 null 键
* 线程不同步-- 效率高-- 不安全
*
* Map集合中的键要求保证唯一, 那么,HashMap集合中,如何保证 键 的唯一呢?
* 重写 hashCode() 与 equals()方法
*
* 注意: 这里面的唯一指的是 键唯一, 针对键有效, 与 值 无关
*
* 使用HashMap存储字符串 并遍历
* 键 String 值 String
*/
public class HashMapDemo {
public static void main(String[] args) {
//创建HashMap集合
HashMap<String,String> hm = new HashMap<String,String>();
//添加键值对元素 到集合
hm.put("谢霆锋", "张柏芝");
hm.put("李亚鹏", "王菲");
hm.put("汪峰", "章子怡");
//遍历方式1 键找值
//a: 获取到Map集合中所有的键
Set<String> keys = hm.keySet();
//b: 获取到每一个键
for (String key : keys) {
//c: 通过键,找对应的值
String value = hm.get(key);
System.out.println(key+"---"+value);
}
//遍历方式2 键值对 找键 找值
//a: 获取所有的键值对元素对象
Set<Entry<String, String>> entrySet = hm.entrySet();
//b: 获取到每一个键值对元素对象
for (Entry<String, String> entry: entrySet) {
//c: 通过当前的键值对元素对象, 获取键,获取值
String key = entry.getKey();// 获取键
String value = entry.getValue(); //获取值
System.out.println(key+"---"+value);
}
}
}
</span></span>
TreeMap:
底层: 二叉树结构
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_05_TreeMap;
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;
}
}
</span></span>
package cn.itcast_05_TreeMap;
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;
}
}
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_05_TreeMap;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
/*
* TreeMap集合键是Student值是String的案例
* 键是Student
* 值是String
*
* 注意了, 键是自定义类对象, 需要实现自然排序接口,或者比较器接口(推荐)
*/
public class TreeMapDemo2 {
public static void main(String[] args) {
//创建TreeMap集合对象, 同时实现比较器
TreeMap<Student,String> map = new TreeMap<Student,String>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//名字
int num = s1.getName().compareTo(s2.getName());
//年龄
int result = (num==0) ? (s1.getAge() - s2.getAge()) : num ;
return result;
}
});
//添加元素到集合
Student s1 = new Student("z周瑜", 28);
Student s2 = new Student("x小乔", 18);
Student s3 = new Student("d大乔", 19);
map.put(s1, "itcast001");
map.put(s2, "itcast002");
map.put(s3, "itcast003");
map.put(s1, "itcast110");
//遍历
Set<Student> keys = map.keySet();
//获取到每一个键
for (Student key : keys) {
//键 找 值
String value = map.get(key);
System.out.println(value +"---"+key.getName()+"---"+key.getAge() );
}
}
}
</span></span>
LinkedHashMap:
底层: 哈希表结构 + 链表结构
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_04_LinkedHashMap;
import java.util.LinkedHashMap;
import java.util.Set;
/*
* LinkedHashMap<K,V>:
* 底层: 哈希表 + 链表
* 有序(元素的存与取顺序一致)
* 线程不同步 -- 效率高-- 不安全
*/
public class LinkedHashMapDemo {
public static void main(String[] args) {
//创建集合对象
LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();
//添加元素到集合
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历 键找值
Set<String> keys = map.keySet();
for (String key : keys) {
//键 找 值
String value = map.get(key);
System.out.println(key +"---"+value);
}
}
}
</span></span>
Collections:
集合工具类
public static <T> void sort(List<T> list) 排序
public static <T> int binarySearch(List<?> list,T key) 二分查找
public static <T> T max(Collection<?> coll) 最大值
public static void reverse(List<?> list) 反转
public static void shuffle(List<?> list) 随机打乱
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) 替换
<span style="font-size:18px;"><span style="font-size:18px;">package cn.itcast_07_Collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
* Collections类概述
针对集合操作 的工具类
Collections成员方法
public static <T> void sort(List<T> list) 排序
public static <T> int binarySearch(List<?> list,T key) 二分查找
public static <T> T max(Collection<?> coll) 最大值
public static void reverse(List<?> list) 反转
public static void shuffle(List<?> list) 随机打乱
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) 替换
*/
public class CollectionsDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(12);
list.add(8);
list.add(11);
list.add(11);
list.add(11);
list.add(11);
list.add(7);
list.add(23);
list.add(54);
list.add(22);
list.add(1);
list.add(79);
System.out.println(list);
System.out.println("排序后:");
Collections.sort(list);
System.out.println(list);//[1, 7, 8, 11, 12, 22, 23, 54, 79]
System.out.println("二分查找 12 索引:"+ Collections.binarySearch(list, 12));
System.out.println("最大值:" + Collections.max(list));
System.out.println("反转后");
Collections.reverse(list);
System.out.println(list);
System.out.println("随机打乱后");
Collections.shuffle(list);
System.out.println(list);
System.out.println("替换后:");
System.out.println(Collections.replaceAll(list, 11, 111));
System.out.println(list);
}
}
</span></span>
HashMap和Hashtable的区别?
HashMap
线程不同步-- 不安全--效率高
可以使用null键 null值
Hashtable
线程同步 -- 安全 -- 效率低
不能使用null键 null值
<span style="font-size:18px;">package cn.itcast_06_Map_Test;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
/*
* "aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
*
* 分析:
* 通过结果可以看出 字母与次数之间有对应关系, 我们可以采用Map集合
* 又由于结果是一个有序的结果,我们最终决定采用 TreeMap集合
* a(5)
* TreeMap<Character, Integer>
* a 1++ ++
* b 1
*
* 1: 定义一个字符串 "aababcabcdabcde"
* 2:定义一个集合 TreeMap<Character, Integer> 用来存储字母与次数
* 3:遍历字符串,得到每一个字母
* 4:判断当前字母在集合中是否存在
* 存在:
* 把当前字母 在集合中存储的次数获取出来, 次数加1后,再存进去
* 不存在:
* 把当前字母 与 次数1 存进去
* 5: 组装结果字符串 a(5)b(4)c(3)d(2)e(1)
* 通过遍历Map集合得到每一个键与值 ,然后拼装
*/
public class TreeMapDemo {
public static void main(String[] args) {
//1: 定义一个字符串 "aababcabcdabcde"
String str = "aababcabcdabcde";
//2:定义一个集合 TreeMap<Character, Integer> 用来存储字母与次数
TreeMap<Character, Integer> map = new TreeMap<Character, Integer>(); // 自然排序
//3:遍历字符串,得到每一个字母
for (int i =0; i< str.length(); i++) {
//得到每一个字母
char ch = str.charAt(i);
//4:判断当前字母在集合中是否存在
if (map.containsKey(ch)) {
//把当前字母 在集合中存储的次数获取出来, 次数加1后,再存进去
int count = map.get(ch);
count++;
map.put(ch, count);
} else {
//把当前字母 与 次数1 存进去
map.put(ch, 1);
}
}
//System.out.println(map);
//5: 组装结果字符串 a(5)b(4)c(3)d(2)e(1)
//通过遍历Map集合得到每一个键与值 ,然后拼装
StringBuilder sb = new StringBuilder();
//方式2 键值对 找键 找值
Set<Entry<Character, Integer>> entrySet = map.entrySet();
//得到每一个键值对元素
for (Entry<Character, Integer> entry : entrySet) {
//找键 --- 字母
Character c = entry.getKey();
//找值 --- 次数
Integer n = entry.getValue();
sb.append(c).append("(").append(n).append(")");//a(5)
}
//打印结果
System.out.println(sb.toString());
}
}
</span>