一、练习
package com.day5_22;
/**
* @author alice_huijing
* @version 1.0
*/
public class Test01 {
public static void main(String[] args) {
/*
第一题:1、将字符串中指定部分进行反转,比如将 abcdef中的bcde反转为aedcbf
2、编写方法public static String reverse(String str, int start, int end)
*/
System.out.println("==交换之前==");
System.out.println("abcdef");
System.out.println("==交换之后==");
try {
System.out.println(reverse("abcdef", 1, 4));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 1\
* 因为String是不能修改的,需要转换成为char数组,char数组的元素可以交换
* char[] chars = str.toCharArray();
* 2\
* 什么时候产生交换的行为,现在有两个箭头分别指向start的位置和end的位置,start的位置
* 的箭头往前面移动,end的箭头往后面移动,当两个箭头错开或者是指向同一个元素的时候就不需要发生交换的行为了。
* 3\
* 最后再将char数组转换成String返回
* 4\
* 规避一下数组越界的问题
* 编程思想:写验证代码的时候,写出正确的情况然后取反即可,这种是最好的,正确的情况容易想到
* @param str
* @param start
* @param end
* @return
*/
public static String reverse(String str, int start, int end) {
if(!(str!=null && start >=0
&& end > start
&& end < str.length())) {
throw new RuntimeException("参数不正确");
}
char[] chars = str.toCharArray();
char temp = ' ';
for (int i = start,j = end; i < j; i++, j--) {
temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return new String(chars);
}
}
package com.day5_22;
/**
* @author alice_huijing
* @version 1.0
*/
/*
第二题
输入用户名,密码,邮箱,如果信息录入成功,则提示注册成功,否则生成异常对象
要求:
1、用户名长度为2或者是3或者是4
2、密码的长度为6,要求全部是数字
3、邮箱中包含@和.并且@在。的前面
isDigital
*/
public class Test02 {
public static void main(String[] args) {
String name = "ali";
String pwd = "123456";
String email = "alice@gmail.com";
try {
userRegister(name, pwd, email);
System.out.println("恭喜你,注册成功!");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 输入姓名,密码,邮箱-三个参数
* 确定方法名称-用户注册
* 抛出异常,返回值为void
* main中调用设置为static
* @param name
* @param pwd
* @param email
*/
public static void userRegister(String name, String pwd, String email) {
// 校验
if (!(name != null & pwd != null && email != null)) {
throw new RuntimeException("参数不能为null");
}
// 1、确定用户名
int userLength = name.length();
if (!(userLength>=2 && userLength<=4)) {
throw new RuntimeException("用户名长度为2或者3或者4");
}
// 2、判断密码
if (!(pwd.length()==6 && isDigital(pwd))) {
throw new RuntimeException("密码长度为6,要求全部是数字");
}
// 3、@和.
int i = email.indexOf('@');
int j = email.indexOf('.');
if (!(i > 0 && j > i)) {
throw new RuntimeException("邮箱中包含@和.,并且@在.的前面");
}
}
public static boolean isDigital(String str) {
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] < '0' || chars[i] > '9') {
return false;
}
}
return true;
}
}
package com.day5_22;
/**
* @author alice_huijing
* @version 1.0
*/
/*
第三题:
1、编写程序,输入形式为:Han Shun Ping的人名,以Ping,Han .S的形式打印出来
其中.S是中间单词的首字母。
2、例如输入"Willian Jefferson Clinton",输出形式为:Clinton,Willian.J
*/
//public class Test03 {
// public static void main(String[] args) {
// String name = "Willian Jefferson Clinton";
// printName(name);
// }
// public static void printName(String str) {
// if (str == null) {
// System.out.println("str 不能为空");
// return ;
// }
// String[] names = str.split(" ");
// if (names.length != 3) {
// System.out.println("输入的字符串格式不正确");
// return ;
// }
// String format = String.format("%s,%s .%c", names[2], names[0], names[1].toUpperCase().charAt(0));
// System.out.println(format);
// }
//}
/*
第四题:
输入字符串,判断里面有多少个大写字母,多少个小写字母,多少个数字
*/
public class Test03 {
public static void main(String[] args) {
String str = "Alice Python AA107107@Ww";
countStr(str);
}
public static void countStr(String str) {
if (str == null) {
System.out.println("输入不能为null");
return;
}
int strLen = str.length();
int numCount = 0;
int lowerCount = 0;
int upperCount = 0;
int otherCount = 0;
for (int i = 0; i < strLen; i++) {
if (str.charAt(i) >= '0' && str.charAt(i) <= '9') {
numCount++;
} else if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z') {
lowerCount++;
} else if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') {
upperCount++;
} else {
otherCount++;
}
}
System.out.println("数字有:" + numCount);
System.out.println("小写字母有:" + lowerCount);
System.out.println("大写字母有:" + upperCount);
System.out.println("其他有:" + otherCount);
}
}
package com.day5_22;
/**
* @author alice_huijing
* @version 1.0
*/
public class Test04 {
public static void main(String[] args) {
String s1 = "hspedu"; // 这里直接在常量池中创建一个字符串常量,s1指向它
Animal a = new Animal(s1); // 在堆中创建一个Animal对象,对象的name属性指向常量池中已经存在的hspedu
Animal b = new Animal(s1); // 在堆中创建一个Animal对象,对象的name属性指向常量池中已经存在的hspedu
System.out.println(a==b); // 当前a和b是两个堆中不同对象的引用,所以结果为False
System.out.println(a.equals(b)); // 因为Animal中没有重写从Object继承下来的equals,所以这里判断的还是是否==,结果False
System.out.println(a.name == b.name); // 因为hspedu已经存在,所以就不用创建新的,所以两个对象的属性都是这个,true
String s4 = new String("hspedu"); // 创建一个字符串对象,堆中对象中还有一个value属性来指向池中的hspedu
String s5 = "hspedu"; // hspedu已经存在,所以s5直接指向池中的hspedu
System.out.println(s1 == s4); // s1直接指向常量池当中的hspedu,s4指向的是堆当中的一个字符串对象,所以为false
System.out.println(s4==s5); // s4指向的是堆当中的一个字符串对象,s5指向的是池中的hspedu,结果为false
String t1 = "hello" + s1; // 这里底层优化,需要在堆当中创建一个字符串对象,属性value指向常量池的hellohspedu
String t2 = "hellohspedu"; // 这个字符串常量已经存在,直接指向即可。
System.out.println(t1.intern()==t2); // intern相当于指向的是最终常量池的字符串常量,t2是直接指向,所以这里为true
}
}
/*
false
false
true
false
false
true
*/
class Animal {
String name ;
public Animal(String name) {
this.name = name;
}
}
二、Collection接口(未完)
package com.day5_22;
/**
* @author alice_huijing
* @version 1.0
*/
/*
目录:
集合框架体系图
Collection接口 特点 方法
Collection接口的子接口:List实现类:ArrayList,LinkedList,Vector
Collection接口的子接口:Set实现类:HashSet,LinkedHashSet
Map接口 特点方法 遍历方式
Map接口的实现类:HashMap、Hashtable等
Collections工具类的使用
即:
集合框架体系
Collection
List
ArrayList
LinkedList
Vector
Set
HashSet
LinkedHashSet
TreeSet
Map
HashMap
Hashtable
LinkedHashMap
TreeMap
Properties
Collections
集合的理解以及好处:
前面我们保存多个数据使用的是数组,数组有很多不足的地方,分析一下!:
数组,
1、数组长度开始时候必须指定,而且一旦指定,不能更改
2、保存的时候必须为同一类型的元素
3、使用数组进行增加元素比较麻烦
集合,
1、可以动态保存任意多个对象,使用比较方便!
2、提供了一系列方便操作对象的方法
3、使用集合添加,删除新元素简单明了
*/
public class Collection05 {
}
package com.day5_22;
import java.util.ArrayList;
import java.util.HashMap;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection06 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(); // 单列集合
arrayList.add("jack"); // 单列数据
arrayList.add("tom");
HashMap hashMap = new HashMap(); // 双列集合
hashMap.put("NO1", "北京"); // 双列数据
hashMap.put("NO2", "上海");
}
}
/*
集合的框架体系(关于集合的框架体系要求背诵)
进入到Collection接口可以发现,该接口继承了一个Iterable的接口
而Collection下面还有两个比较重要的子接口
List和Set
而List下面有三个重要的实现子类:
Vector
LinkedList 这个是链表的
ArrayList 这个是数组的
而Set下面有两个重要的实现子类:
HashSet
TreeSet
以上是一组集合
另外还有一组集合Map
Map接口下面有三个实现子类:
Hashtable,HashMap,TreeMap
在Hashtable下面有子类Properties
HashMap下面有子类LinkedHashMap
总结:
1、集合主要分成两组
一组是单列集合,一组是双列集合
什么是单列集合,什么是双列集合?
2、Collection接口下面有两个重要的子接口,List和Set
它们的实现子类都是单列集合
3、Map接口的实现子类是双列集合,存放的是K-V这样的数据(键值对)
*/
package com.day5_22;
import java.util.ArrayList;
import java.util.List;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection08 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
/*
接口不能被实例化,所以以一个子类来讲解这个接口里面的常用方法。--ArrayList
1)add方法,添加单个元素
2)remove,删除指定元素
3)contains,查找元素是否存在
4)size,获取元素的个数
5)isEmpty,判断是否为空
6)clear,清空
7)addAll,添加多个元素
8)containsAll,查找多个元素是否都存在
9)removeAll,删除多个元素
10)说明,以ArrayList实现类来演示
*/
// 1、创建一个ArrayList
// 使用子接口来接收
List list = new ArrayList();
// 2、add
list.add("alice"); // 这里可以看到参数是一个Object的,所以只要是Object类以及Object的子类都可以放到list里面
list.add(10); // 这里放整数有一个自动装箱的过程。
list.add(true); // 也有一个自动装箱的过程
System.out.println("list = " + list); // list = [alice, 10, true]这里是对象了
// 这里相当于list.add(new Integer(10)),存放的是对象。
// 3、remove,删除指定的元素,不想要可以这样删除
// 这里的remove方法是被重载了的
// 可以指定删除索引,也可以指定删除哪一个元素Object
// Object的是返回boolean,如果是按照索引是返回被删除的对象
list.remove(0); // 删除第一个元素
System.out.println("list = " + list); // alice没有了
// list.remove("alice"); // 这个就是指定删除某个对象元素,或者true或者10
// 我们通过list来进行数据的添加和删除非常方便,比数组方便。
// 4、contains,查找元素是否存在
System.out.println(list.contains("alice")); // 之前被删除了所以已经没有了
// 5、size可以返回元素的个数
System.out.println(list.size()); // 目前里面应该有二个元素,之前删除掉了一个元素
// 6、isEmpty,判断是否为空
System.out.println(list.isEmpty()); // 有两个元素,所以当前为false
// 7、clear 清空
list.clear(); // 再输出来看list = []
System.out.println("list = " + list);
// 8、addAll可以添加多个元素,可以传入一个Collection c,也就是实现了这个接口的类的对象都可以传入进去
ArrayList list2 = new ArrayList();
list2.add("红楼梦");
list2.add("三国演义");
list.addAll(list2); // add相当于python里对列表的append的操作,而addAll相当于python的extend的操作,打散
System.out.println("list = " + list);// 之前被清空的,现在传入了一个list进去现在又有了元素
// 9、containsAll 查看多个元素是否都存在
System.out.println(list.containsAll(list2)); // 看看这个list里面是否有list2的所有元素,刚刚传入进去了,确实有
// 10、removeAll可以删除多个元素
list.add("聊斋");
list.removeAll(list2); // 删除含有list2中的所有元素
System.out.println("list = " + list);
}
}
/*
实现了Collection的子类有哪些特点:
子类有Vector,ArrayList,LinkedList,HashSet,TreeSet
Collection接口里面有什么方法也了解一下。
这个Collection接口继承了Iterable,
public interface Collection<E> extends Iterable<E>
1)Collection实现子类可以存放多个元素,每个元素可以是Object
2)有些Collection的实现类,可以存放重复的元素,有些不可以
3)有些Collection的实现类,有些是有序的比如List,有些是无序的,比如Set
4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的。
*/
package com.day5_22;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection09 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
System.out.println("col = " + col);
// 现在希望能够遍历集合
// 1、先得到这个集合的对应的迭代器Iterator
// 只要是实现了这个Collection接口的就必须实现Iterator方法
Iterator iterator = col.iterator();
// 2、使用while循环遍历
while (iterator.hasNext()) { // 看看集合中是否看存在数据,如果没有数据就直接退出循环
Object obj = iterator.next(); // 因为什么都可以放,所以返回的是一个Object的,需要注意。
// 3、得到这个元素对象之后就可以使用
System.out.println("obj = " + obj); // 运行类型取决于真正的类型,这里相当于多态数据的时候我们讲过的。
// 这里在进行while循环的时候可以使用快捷键快速生成itit然后回车即可生成
}
// tip,通过Ctrl + J的方式可以将当前IDEA中存在的所有快捷模板提示出来,比如itit的,sout的等。
/*
细节说明,在使用迭代器进行迭代的时候,当你将while循环退出的时候需要进行一点说明:
当退出while循环之后,我们这个游标,就是这里的箭头已经指向集合中最后的位置了,不能再取了
如果再取就会抛出异常。
*/
// 这个地方再取会出现异常
// iterator.next(); // java.util.NoSuchElementException
/*
4、如果希望再次遍历,需要重置我们的迭代器,就是相当于原先这个箭头是在集合的开始的,我们需要将箭头复位
iterator = col.iterator(); // 这样就行了。
*/
iterator = col.iterator();
System.out.println(iterator.next()); // 重置了底层的箭头,这样又能够访问了。
}
}
class Book {
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
/*
来看Collection接口遍历元素的方式,只要是实现了这个接口的类在遍历包含的元素的时候可以又两种方式
第一种是使用Iterator迭代器的方式
这个Iterator是怎么来的?
Collection上面还有一个父接口Iterable,里面有一个非常重要的方法
可以通过iterator方法返回一个迭代器对象
我们可以使用这个迭代器对象来进行所有元素的遍历,但凡是实现了Collection的子类,都可以获得一个迭代器
来遍历里面的所有元素。
1)Iterator对象称为迭代器,主要是用来遍历Collection集合中的元素
2)所有实现了Collection接口的集合类都有一个iterator方法,用来返回一个实现了Iterator接口的对象,
即可以返回一个迭代器。
3)Iterator仅仅用于遍历集合,Iterator本身并不存放对象。
具体底层的实现就是数据结构
得到迭代器之后,每次调用next就会往下移动一次得到下一个数据,移动到最后一个的时候娶不到东西就会退出
在next之后前面一定要有一个动作就是hasNext,这个是判断是否还有下一个元素,如果没有就返回false,这个循环就会结束,
也就是遍历也就会结束,只会在这个集合的最后一个元素结束。
next可以让指针往下面移动,将指向的元素返回回来,这个是next方法的作用。
1)下移
2)将下移之后位置的元素返回
Iterator接口的方法:
1)hasNext
2)next
3)remove,这个使用比较少
注意,在调用iterator.next()方法之前必须要先调用iterator.hasNext()进行检测,如果不调用,且下一条记录无效,直接
调用it.next()会抛出NoSuchElementException异常。
*/
package com.day5_22;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection10 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
// 1、创建集合
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
// 2、使用增强for循环
for(Object book: col) {
System.out.println("book = " + book);
} // 这个比使用迭代器看起来比较方便,效果还是一样的,这里的增强for不仅可以适用于集合还可以使用在数组上,前面使用过。
int[] nums = {1, 8, 10, 90};
for (int i: nums) {
System.out.println("i = " + i);
}
/*
增强for的底层还是迭代器,我们可以在增强for上面下断点,进去看
也是先调用了iterator,new了迭代器对象,然后调用hashNext
然后是next方法,所以这个看到的增强for循环也是迭代器,增强for就是一个简化版的迭代器遍历方式。
快捷方式是I
for (Object o :) {
}
*/
}
}
/*
Collection接口遍历对象方式二,可以使用for循环增强来遍历
增强for循环是一个简化版的iterator,可以代替iterator迭代器
本质是一样的,用于遍历集合或者是数组。
基本语法是:
for(元素类型 元素名: 集合或者数组名) {
访问元素
}
*/
package com.day5_22;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection11 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList(); // 因为ArrayList实现了List接口,所以可以使用List接收
list.add(new Dog("小黑", 3));
list.add(new Dog("大黄", 100));
list.add(new Dog("大壮", 8));
// 1、先使用for循环增强
for (Object dog : list) {
System.out.println("dog = " + dog);
}
// 2、使用迭代器的方式,通过list拿到一个迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object dog = iterator.next();
System.out.println("dog = " + dog);
}
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
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 "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
/*
1、创建3个Dog{name, age}对象,放入到ArrayList中,赋给List引用,
2、使用迭代器和增强for循环两种方式来遍历
3、重写Dog的toString方法,输出name和age
*/
package com.day5_22;
import java.util.ArrayList;
import java.util.List;
/**
* @author alice_huijing
* @version 1.0
*/
public class Collection12 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
// List list = new ArrayList();
// list.add("alice");
// list.add("tom");
// list.add("mary");
// list.add("how");
// System.out.println("list = " + list); // list = [alice, tom, mary, how],添加顺序和取出顺序是一样的。
//
// // 第二个是还可以重复
// list.add("tom");
// System.out.println("list = " + list); // list = [alice, tom, mary, how, tom]
//
// // 然后第三个是List集合的每个元素都有其对应的顺序索引,即支持索引
// // 索引还是从零开始的
// System.out.println(list.get(3)); // how
// JDK中List接口的实现子类有非常多
// 这里例举出:Vector ArrayList LinkedList
// 实现类有:AbstractList,AbstractSequentialList,ArrayList,AttributeList,CopyOnWriteArrayList,
// LinkedList,RoleList,RoleUnresolvedList,Stack,Vector
/*
List接口的常用方法
List集合里添加了一些根据索引来操作集合元素的方法
1)void add(int index, Object ele),在index位置插入ele元素
2)boolean addAll(int index, Collection eles),从index位置开始将eles中的所有元素添加进来。
3)Object get(int index),获取指定index位置的元素
4)int indexOf(Object obj),返回obj在集合中首次出现的位置
5)int lastIndexOf(Object obj),返回obj在当前集合中末次出现的位置
6)Object remove(int index),移除指定index位置的元素,并返回此元素
7)Object set(int index, Object ele),设置指定index位置的元素为ele,相当于是替换。
8)List subList(int fromIndex, int toIndex),返回从fromIndex到toIndex位置的子集合
这八个方法是需要掌握的。
*/
// 1、创建一个ArrayList
List list = new ArrayList();
// 2、add方法,这里的add方法相当于是插入
list.add("张三丰");
list.add("贾宝玉");
// 在index位置插入元素,在张三丰和贾宝玉之间插入一个人
// 即,index为1的位置插入一个对象
list.add(1, "alice"); // 如果没有索引默认是加入到最后的。
System.out.println("list = " + list);
// 3、addAll,在上一个的基础上,将这个集合里面的元素插入进去
List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1, list2);
System.out.println("list = " + list);
// 4、get方法已经讲过
// 5、indexOf,返回首次出现的位置,和查找差不多
System.out.println(list.indexOf("tom")); // 0 1 2,在index为2的位置
// 6、listIndexOf,返回最后一次出现的位置
list.add("alice");
System.out.println("list = " + list);
System.out.println(list.lastIndexOf("alice"));
// 7、将指定索引位置的元素删除
list.remove(0);
System.out.println("list = " + list);
// 8、set,替换
list.set(1, "玛丽有只小羔羊");
System.out.println("list = " + list);
// 加入索引位置给的是一个不存在的会抛出异常,索引越界
// 如果这里写5看可不可以,也是不行的,也是索引越界,索引一定要是存在的
// 9、subList,返回指定范围的子集合
List resList = list.subList(0, 2);
System.out.println("resList = " + resList);
// [),返回的是一个前闭,后开的 0,1
}
}
/*
前面讲了Collection这个接口的相关方法,这里再讲List这个接口的相关方法,以及实现了这个接口的子类
这里使用ArrayList类来讲
List里面的接口,Set那一边的不能使用,所以这个时候就要开始细化了。
实现了List接口的有哪些特点:
1)List集合类中元素有序(即添加顺序和取出来的顺序是一样的),并且是可以重复的。
2)List集合中每个元素都有其对应的顺序索引,即支持索引。
3)List容器中的元素都对应一个整数类型的序号记载其在容器中的位置,可以根据序号取容器中的元素。
*/