----------------------
String类
-------------------------------------------------------------------------------------------------------------------------------------
字符串是一个特殊的对象。
字符串一旦初始化就不可以被改变。
String str = “abc”;
String str1 = new String(“abc”);
class StringDemo
{
public static void main(String[] args)
{
/*
String s1 = "abc";//s1是一个类类型变量, "abc"是一个对象。
//字符串最大特点:一旦被初始化就不可以被改变。
String s2 = new String("abc");
//s1和s2有什么区别?
//s1在内存中有一个对象。
//s2在内存中有两个对象。
System.out.println(s1==s2);
System.out.println(s1.equals(s2));//String类复写了Object类中equals方法,
//该方法用于判断字符串是否相同。
*/
String s = "abcde";
method_1(s);
}
/*
String类是对字符串事物的描述。
该类定义了专门用于操作字符串的方法。
"abc":
*/
public static void method_1(String s)
{
char ch = s.charAt(3);
System.out.println("ch="+ch);
int num = s.codePointAt(3);
System.out.println("num="+num);
String s1 = "qq";
s1 = s1.concat("mm");
System.out.println("s1="+s1);
System.out.println("qq"+"mm");
String a = "opq";
String b = "opq";
System.out.println("a==b:"+(a==b));
}
}
有什么区别 ?
String类部分方法
char charAt(int index)
int length()
char[] toCharArray();
int indexOf(String str);
boolean endsWith(String str);
String[] split(String reg);
String substring(int index);
String(char[] arr);
StringBuffer
字符串的组成原理就是通过该类实现的。
StringBuffer可以对字符串内容进行增删。
StringBuffer是一个容器。
很多方法与String相同。
StingBuffer是可变长度的。
StringBuffer特有方法
StringBuffer append(int x);
StringBuffer delete(int start, int end );
StringBuffer insert(int index,String str);
StringBuffer reverse();
JDK1.5出现一个StringBuilder,区别是 StringBuffer是同步的,StringBuilder是非同步 的。
/*
StringBuffer是字符串缓冲区。
是一个容器。
特点:
1,长度是可变化的。
2,可以字节操作多个数据类型。
3,最终会通过toString方法变成字符串。
C create U update R read D delete
1,存储。
StringBuffer append():将指定数据作为参数添加到已有数据结尾处。
StringBuffer insert(index,数据):可以将数据插入到指定index位置。
2,删除。
StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。
StringBuffer deleteCharAt(index):删除指定位置的字符。
3,获取。
char charAt(int index)
int indexOf(String str)
int lastIndexOf(String str)
int length()
String substring(int start, int end)
4,修改。
StringBuffer replace(start,end,string);
void setCharAt(int index, char ch) ;
5,反转。
StringBuffer reverse();
6,
将缓冲区中指定数据存储到指定字符数组中。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
JDK1.5 版本之后出现了StringBuilder.
StringBuffer是线程同步。
StringBuilder是线程不同步。
以后开发,建议使用StringBuilder
升级三个因素:
1,提高效率。
2,简化书写。
3,提高安全性。
*/
class Demo
{
}
class StringBufferDemo
{
public static void main(String[] args)
{
//method_update();
StringBuilder sb = new StringBuilder("abcdef");
char[] chs = new char[6];
sb.getChars(1,4,chs,1);//将
for(int x=0; x<chs.length; x++)
{
sop("chs["+x+"]="+chs[x]+";");
}
draw(3,6);
draw(8,9);
// StringBuilder sb1 = new StringBuilder();
// sb1.append(new Demo()).append(new Demo());
// sop("sb1="+sb1);
}
public static void method_update()
{
StringBuffer sb = new StringBuffer("abcde");
// sb.replace(1,4,"java");
sb.setCharAt(2,'k');
sop(sb.toString());
}
public static void method_del()
{
StringBuffer sb = new StringBuffer("abcde");
// sb.delete(1,3);
//清空缓冲区。
//sb.delete(0,sb.length());
//sb.delete(2,3);
sb.deleteCharAt(2);
sop(sb.toString());
}
public static void method_add()
{
StringBuffer sb = new StringBuffer();
//sb.append("abc").append(true).append(34);
// StringBuffer sb1 = sb.append(34);
// sop("sb==sb1:"+(sb==sb1));
sb.insert(1,"qq");
sop(sb.toString());//abctrue34
//sop(sb1.toString());
}
public static void sop(String str)
{
System.out.println(str);
}
public static void draw(int row,int col)
{
StringBuilder sb = new StringBuilder();
for(int x=0; x<row; x++)
{
for(int y=0; y<col; y++)
{
sb.append("*");
}
sb.append("\r\n");
}
sop(sb.toString());
}
}
---------------------------------------------------------------------------------------------------------------------------------------------------------
基本数据类型对象包装类
将基本数据类型封装成对象的好处在于可以在 对象中定义更多的功能方法操作该数据。
常用的操作之一:用于基本数据类型与字符串 之间的转换。
例:Integer的parseInt方法,intValue方法。
例程
基本数据类型对象包装类新特性
JDK1.5以后,简化了定义方式。
• Integer x = new Integer(4);可以直接写成
• Integer x = 4;//自动装箱。
• x = x + 5;//自动拆箱。通过intValue方法。
需要注意:
• 在使用时,Integer x = null;上面的代码就会出 现NullPointerException。
/*
基本数据类型对象包装类。
byte Byte
short short
int Integer
long Long
boolean Boolean
float Float
double Double
char Character
基本数据类型对象包装类的最常见作用,
就是用于基本数据类型和字符串类型之间做转换
基本数据类型转成字符串。
基本数据类型+""
基本数据类型.toString(基本数据类型值);
如: Integer.toString(34);//将34整数变成"34";
字符串转成基本数据类型。
xxx a = Xxx.parseXxx(String);
int a = Integer.parseInt("123");
double b = Double.parseDouble("12.23");
boolean b = Boolean.parseBoolean("true");
Integer i = new Integer("123");
int num = i.intValue();
十进制转成其他进制。
toBinaryString();
toHexString();
toOctalString();
其他进制转成十进制。
parseInt(string,radix);
*/
class IntegerDemo
{
public static void sop(String str)
{
System.out.println(str);
}
public static void main(String[] args)
{
//整数类型的最大值。
//sop("int max :"+Integer.MAX_VALUE);
// 将一个字符串转成整数。
int num = Integer.parseInt("123");//必须传入数字格式的字符串。
//long x = Long.parseLong("123");
// sop("num="+(num+4));
// sop(Integer.toBinaryString(-6));
// sop(Integer.toHexString(60));
int x = Integer.parseInt("3c",16);
sop("x="+x);
}
}
-------------------------------------------------------------------------------------------------------
集合类
集合的由来:
java是一种面向对象的语言,对现实世界中的事物均以对象体现,为了方便对多个对象进行操作(对象数组的局限性)
为了方便我们对多个对象进行操作,java是提供了一种新的容器,就是集合类(框架)
:用于存储对象的容器
: 该容器的长度是可变的
:集合中存储的对象可以是任意类型的
集合与数组的区别:
集合:
长度是可变的
集合只能存储对象类型
集合可以存储多种引用数据类型的元素
数组:
长度是固定的
数组可以存储对象类型,也可以存储基本数据类型
数组存储的多个元素是同一种数据类型
由于数据在存储的时候,数据结构不一样,所以,就会出现多种类型的集合方便我们操作。
不管你是哪种类型的集合,都是满足一些常见的操作
集合框架的由来:(理解)
由于多种集合类的数据结构不同,通过不断的向上抽取,形成了集合的体系结构。
学习和使用体系结构的方式。
学习顶层,因为顶层定义的是共性的东西。
使用底层,因为底层是具体实现的东西。
数据结构:
组织数据的方式。
但是,操作的方式又不一样,这个时候,就要向上抽取,最终形成一个集合体系结构
Collection接口功能: (重点,能够把数据放到集合中,然后把数据从集合中遍历出来)
1、添加元素:
boolean add(Object obj);//添加单个元素
boolean addAll(Collection c);添加多个元素
2、判断元素:
boolean contains(Object obj);判断元素是否存在。
boolean containsAll(Collection c);判断一个集合的元素是否包含在当前集合中
boolean isEmpty();判断集合是否为空
3、删除元素:
void clear();移除所有元素。这个方法太暴力了。
boolean remove(Object o);移除单个元素。
boolean removeALL(Collection c);移除多个元素。
4、获取元素:
Iterator iterator();返回集合上的一个迭代器
5、交集:
boolean retainAll(Collection c)交集
6、集合元素的个数:
int size();元素个数
7、把集合转成数组
Object[] toArray(); 建议不要使用此方法进行集合的遍历
迭代器的使用:
Iterator iterator();
迭代器中的三个方法:
boolean hasNext(); 判断是否还有元素
Object next():获取元素,并且还可以自动指向下一个元素
void remove(); 删除元素:
原理: 每种集合的存储方式不一样,所以,它的取出方式也不一样
但是,他们都应该有获取的功能,所以,进行了抽取
当你遍历某种类型的集合的时候,就由该类型的集合自己去实现迭代器接口
----------------------------------------------------------------------------------------------------------
集合操作的思路:
A:创建集合对象
B:创建元素对象
C:把元素添加到集合中
D:遍历集体
**通过集合对象获取迭代器对象
**调用迭代器对象的hasNext()方法判断是否还有元素
**调用迭代器对象的next()方法获取元素。
<span style="font-size:14px;">class IteratorDemo
{
public static void main(String[] args)
{
//创建集合对象
Collection c=new ArrayList();
//添加元素
c.add("hello");
c.add("world");
c.add("itcast");
System.out.println(c);
//遍历
//用数组实现的,这种不用Object[] toArray()
//迭代器的实现
Iterator it=c.iterator(); //返回的是实现了迭代器接口的子类对象
//获取元素
while(it.hasNext())//判断是否还有元素
{
//
Object obj=it.next()//可以直接由Object类的进行接收
System.out.println(it.next()); //可以直接打印出来
}
}
}</span>
<span style="font-size:14px;">例2:
*
* 集合存储自定义对象
*/
public class CollectionDemo {
public static void main(String[] args) {
// 创建集合对象
Collection c = new ArrayList();
// 创建元素对象
Student s1 = new Student("东方不败", 20);
Student s2 = new Student("林平之", 18);
Student s3 = new Student("岳不群", 19);
// 添加元素
c.add(s1);
c.add(s2);
c.add(s3);
// 遍历元素
// 通过集合对象获取迭代器对象
Iterator it = c.iterator();
// 通过hasNext()方法判断
while (it.hasNext()) {
// 通过next()方获取元素
// System.out.println(it.next().toString());
Student s = (Student) it.next();
// System.out.println(s);
System.out.println(s.getName() + "***" + s.getAge());
}
}
}</span>
-----------------------List------------------------------------------------------------------------------
Collection
|----List
元素有序(存入顺序和取出顺序一致),元素可以重复
|---Set
元素是无序,元素要求唯一
List接口的功能:
1、添加元素
void add(int index,Object obj);指定位置添加指定元素
2、获取元素:
Object get(int index):根据指定索引获取元素
3、列表迭代器
ListIterator listIterator();
4、删除元素:
Object remove(int index);删除指定位置的元素
5、修改元素:
Object set(int index,Object element);修改指定位置的元素
size()方法,它可以获取集合的元素个数。
---------------------------------------------------------------------------------------------------------
<span style="font-size:14px;">例:get方法可以根据指定的索引获取单个元素
那么List体系的集合就多了一种遍历方式:
我们想到了size()方法,它可以获取集合的元素个数
这样的话,我们就可以从0开始获取每个元素的索引
public class ListDemo2
{
//创建集合对象
List list=new new ArrayList();
//添加元素
list.add();
//遍历
for(int x=0;x<list.size();x++)
{
//Stirng s=(String)lis.get(x);
System.out.println(list.get(x));
}
// 这种方法效率不高,可以优化
// list.size()每次循环,都去调用了方法计算集合的元素个数
// 如果元素过多,这种方式不好
// int length = list.size();
// for (int x = 0; x < length; x++) {
// String s = (String) list.get(x);
// System.out.println(s);
// }
在集合元素比较多的时候 可以使用此方法
}</span>
list迭代器的使用
Iterator
hasNext()//判断是否有下一个元素
next(); //读取下一个元素
----ListIterator listIterator();列表迭代器遍历集合元素
有自己的特殊功能,可以实现在逆向遍历
1、Object previous(); //读取一个元素
2、boolean hasPrevious();//判断是否有下一个元素
<span style="font-size:14px;">例1:
Iterator it=it.iterator();
while(lit.hasPrevious())
{
String s=(String)lit.previous();
System.out.println(s);
}
例2:
* 要查找集合中有没有是zhangsan这个字符串。
* 如果有,则在添加一个lisi进去。
*
* Exception in thread "main" java.util.ConcurrentModificationException:并发修改异常
* 在使用迭代器迭代元素的时候,不能使用集合去操作元素,否则,就会出现并发修改异常。
* 那么,请问如何解决这个问题,并能够让元素添加成功:
* 1:在迭代器迭代的过程中,使用迭代器对象去添加元素。
* 2:不用迭代器遍历,用普通for循环遍历,用集合添加元素
*/
public class ListDemo4 {
public static void main(String[] args) {
// 创建集合对象
List list = new ArrayList();
list.add("zhaoliu");
list.add("zhangsan");
list.add("wangwu");
// 请问如何实现我的需求
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
// 判断
if ("zhangsan".equals(s)) {
lit.add("lisi"); //只能使用迭代器进行数据的添加
// list.add("lisi");//用集合对象添加元素会出现并发异常
}
}
/*
//用普通for循环
for(int x=0; x<list.size();x++){
String s = (String)list.get(x);
if("zhangsan".equals(s)){
list.add("lisi");
}
}
*/
System.out.println("list:" + list);
}
}</span>
-----------------------List集合的使用-------------------------------------------------------------
list的儿子的特点:
|---ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
|---Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低
|---LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
使用总结:
我们开发中到底使用哪个子类呢
是否考虑线程安全问题
考虑:
使用Vector
不考虑:
使用ArrayList 或者LinkedList
如果查询多,增删少,用ArrayList
如果查询少,增删少,用LinkedList
如果你还是不知道 ,用ArrayList
// 方式3
//注意:如果使用列表迭代器,我们虽然说了它可以逆序遍历。
//但前提是先正向遍历到结尾了。然后才能逆序遍历。
ListIterator lit = array.listIterator();
while (lit.hasPrevious()) {
String s = (String) lit.previous();
System.out.println(s);
Vector的特殊方法:
1:添加元素
* void addElement(Object obj) -- JDK1.2 后改为了 add(Object obj)
2: 获取元素
* Object elementAt(int index) -- JDK1.2后就改为了 get(int index)
3:遍历元素
Enumeration elements() -- JDK1.2后就改为了 Iterator iterator()
boolean hasMoreElements() -- JDK1.2后就改为了 boolean hasNext()
Object nextElement() -- JDK1.2后就改为了 Object next()
LinkedList的特殊方法:
1:添加元素
void addFirst(Object obj)
void addLast(Object obj)
2:删除元素
Object removeFirst()
Object removeLast()
3:获取元素
Object getFirst()
Object getLast()
例:
public class LinkedListDemo {
public static void main(String[] args) {
// 创建集合对象
LinkedList link = new LinkedList();
// 添加元素
link.add("hello");
link.add("world");
// 特殊添加方法
link.addFirst("itcast");
// 和add方法一样
link.addLast("over");
link.add("java");
// 删除元素
// System.out.println("removeFirst:" + link.removeFirst());
// // NoSuchElementException
// System.out.println("removeLast:" + link.removeLast());
// 获取元素
System.out.println("getFirst:" + link.getFirst());
System.out.println("getLast:" + link.getLast());
// 遍历
Iterator it = link.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
}
}
---------------------------Set集合----------------------------------------------------------------
1:Set(掌握)
(1)Set集合的特点:元素无序,唯一(掌握)
(2)Set的体系结构(掌握):默认是按照字典顺序排列。
Set
|--HashSet
底层数据结构是哈希表。
首先判断哈希值是否相同:
不同:就把元素添加到集合中。
相同:继续进入equals方法比较
返回true,说明元素重复,不存。
返回false,就把元素添加到集合中
<span style="font-size:14px;">如何保证元素的唯一性呢?
它依赖两个方法:hashCode()和equals()
@Override
public int hashCode() {
// return 10;
// 把所有成员(引用类型,基本类型)引用类型的哈希值+基本类型的值返回即可
return this.name.hashCode() + this.age * 17;
}
@Override
public boolean equals(Object obj) {
// System.out.println(this + "***" + obj);
if (this == obj) {
return true;
}
if (!(obj instanceof Person)) {
return false;
}
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}</span>
|--TreeSet
底层数据结构是二叉树。
可以让集合中的元素排序。
如何保证元素的唯一性的呢?
它是根据比较返回的值是0,说明元素是重复的,就不添加。
有两种实现方案:
<span style="font-size:14px;">A:让自定义对象具备比较性
实现Comparable接口
public class Person implements Comparable<Person> {
@Override
public int compareTo(Person p) {
// 成员属性相同的元素为同一对象。我想让元素按照年龄从大到小排序。
// this对象,p对象
// return p.age - this.age;
// 排序的时候,一定要分清楚主次要条件
int num = p.age - this.age;
// // 当年龄相同的时候,你还得比较姓名是否相同
int num2 = (num == 0) ? this.name.compareTo(p.name) : num;
return num2;
// return -1;
}
B:让集合具备比较性
实现Comparator接口
public class MyComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
// return 0;
// 我按照年龄从小到大的顺序比较
int num = p1.getAge() - p2.getAge();
int num2 = (num == 0) ? p1.getName().compareTo(p2.getName()) : num;
return num2;
}
}</span>
<span style="font-size:14px;">例如:
需求:我认为成员属性相同对象即为同一个对象。
*
* 我们重写了equals方法,发现没有达到效果。
* 通过测试,发现根本没有执行equals方法。
* 那么,问题出现在了什么地方呢?
* 通过思考,我们估计问题是出现在了add方法上。
* 所以,我们要研究add方法的源码。
* 通过查看源码,我们发现这个add方法和hashCode()及equals()有关。
* 而且是当哈希值相同的时候,采取执行equals方法。
*
* HashSet是如何保证元素的唯一性的呢?
* 底层数据结构是哈希表。
* 哈希表依赖的是哈希值存储数据的。
* 这个集合首先会根据hashCode方法去判断哈希值是否相同,
* 如果不同,则认为是不同的元素,就添加到集合中。
* 如果相同,就会走equals方法,这样就可以实现根据自己的需求进行比较。
* 如果返回值是true,说明该元素在集合中存在,就不添加。
* 如果返回值是false,直接添加元素。
*/
public class HashSetDemo {
public static void main(String[] args) {
// 创建集合对象
HashSet<Person> hs = new HashSet<Person>();
// 创建元素对象
Person p1 = new Person("林青霞", 25);
Person p2 = new Person("张曼玉", 28);
// 添加元素
hs.add(p1);
hs.add(p2);
// 遍历
Iterator<Person> it = hs.iterator();
while (it.hasNext()) {
Person p = it.next();
System.out.println(p.getName() + "***" + p.getAge());
}
}
}
例如:
我们的TreeSet集合是用于保证元素排序和唯一的。
* 而我们现在的这种操作,并没有让集合中的元素进行排序。
* 通过运行时期的异常,我们可以知道解决
* 方案1:让自定义对象实现Comparable接口
public int compareTo(Person p) {
// 小-大 (this - p)
// 大-小(p - this)
// 按照姓名的从短到长,年龄从大到小顺序排序,并去掉重复元素(姓名和年龄相同即为重复元素)。
// 谁调用this代表谁
int num = this.name.length() - p.name.length();
int num2 = (num == 0) ? (p.age - this.age) : num;
// 追加条件,这个条件是需要我们自己思考的
int num3 = (num2 == 0) ? (this.name.compareTo(p.name)) : num2;
return num3;
}</span>
<span style="font-size:14px;">方案2:让集合具备比较性
* 使用TreeSet带比较器的构造方法
*
* 当Person类具备比较性的时候,是指Person类实现Comparable接口
* 集合也具备比较性的时候,是指TreeSet接受了实现Comparator接口的子类对象
* 以集合具备比较性为主。这个时候,也就是说自定义对象没有必要再去实现比较性的接口。
*
* TreeMap -- put
*
* 需求:成员属性相同的元素为同一对象。我想让元素按照年龄从大到小排序。
*
* TreeSet保证元素唯一性的原理?
* 根据比较方法返回的值是否是0来确定该元素是否是重复元素。
*
* 在用TreeSet保证元素唯一的时候,我们还得考虑元素的排序。
* 而排序的时候,
一定要注意排序的主次要条件。
public class TreeSetDemo3 {
public static void main(String[] args) {
// 创建集合对象
// 以后注意,如果一个方法的参数是一个接口类型的
// 那么,你肯定传递的是一个实现了接口的子类对象
// 匿名对象的使用
TreeSet<Person> ts = new TreeSet<Person>(new MyComparator());
// 创建元素对象
Person p1 = new Person("陆毅", 30);
// 添加元素
ts.add(p1);
// 遍历元素
Iterator<Person> it = ts.iterator();
while (it.hasNext()) {
Person p = it.next();
System.out.println(p.getName() + "***" + p.getAge());
}
}
}
如果两种情况都存在,以B为主。
(4)LinkedHashSet(了解)
底层数据结构是由哈希表和链表组成。
特点:
有序,唯一</span>
-----------------------------Map(掌握)------------------------------------------------------------
(1)Map:存储的是键值对形式的数据的集合。(了解)
(2)Map的特点:(了解)
数据是以键值对形式存在
键不能是重复的
值可以重复
(3)Map接口的功能:(掌握)
A:添加元素
V put(K key,V value)
B:判断元素
boolean containsKey(K key)
boolean containsValue(V value)
boolean isEmpty()
C:删除元素
V remove(K key)
D:长度
int size()
E:获取
V get(k key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
(4)Map案例:(掌握)
Map存储字符串并遍历:
Map<String,String> map = new HashMap<String,String>();
map.put("it001","zhangsan");
map.put("it002","lisi");
map.put("it003","wangwu");
//遍历
//方式1:丈夫找妻子
Set<String> set = map.keySet();
for(String key : set)
{
String value = map.get(key);
System.out.println(key+"***"+value);
}
//方式2:通过结婚证找丈夫和妻子
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> me : entrySet)
{
String key = me.getkey();
String value = me.getValue();
System.out.println(key+"***"+value);
}
Map存储自定义对象并遍历:(自己补齐)
键是字符串
值是学生对象
(5)Map的体系结构(掌握)
Map:(Map体系的数据结构对键有效,跟值无关)
|--HashMap
底层数据结构是哈希表。
如何保证键的唯一性呢?
依赖hashCode()和equals()方法
线程不安全,效率高。允许null键和值。
|--Hashtable
底层数据结构是哈希表。
如何保证键的唯一性呢?
依赖hashCode()和equals()方法
线程安全,效率低。不允许null键和值。
|--TreeMap
底层数据结构是二叉树。
如何保证键的唯一性呢?
两种方式:
自定义元素具备比较性
集合具备比较性
线程不安全,效率高。允许null值,不允许null键。
那么,我们一般使用谁?
如果有排序需求,用TreeMap,否则全部使用HashMap。
(6)案例:
统计字符串中每个字符出现的次数(掌握)
czbk集合的数据存储和遍历(理解)
2:总结集合的使用规律:
是否是键值对形式:
是:Map体系
是否需要排序:
是:TreeMap
不是:HashMap
不知道:HashMap
不是:Collection体系
是否要保证元素唯一:
是:Set
是否要排序:
是:TreeSet
不是:HashSet
不知道:HashSet
不是:List
查询多:ArrayList
增删多:LinkedList
不知道:ArrayList
3:遍历方式:
Collection:
List:
普通for
增强for
//迭代器
Set:
增强for
//迭代器
Map:没有直接遍历方式,需要通过转换。
方式1:丈夫找妻子
//方式2:通过结婚证找丈夫和妻子
4:集合的底层数据结构规律:
ArrayXxx:底层数据结构是数组,查询快,增删慢。
LinkXxx:底层数据结构是链表,查询慢,增删快。
HashXxx:底层数据结构是哈希表。
依赖hashCode()方法和equals()方法
TreeXxx:底层数据结构是二叉树
两种方式实现排序:
自定义元素具备比较性
集合具备比较性