DAY 15

来源:互联网 发布:淘宝排名查询流量 编辑:程序博客网 时间:2024/05/09 13:12

DAY15

回顾内容:

1 List集合子实现类的特点

ArrayList:底层数据结构是数组,查询快,增删慢;线程不安全,不同步执行效率高

LinkedList:底层数据结构是链接列表,查询慢,增删快,线程不安全,不同步,执行效率高

特有功能:

添加功能:

addFirst(Object e);

addLast(Object e);

删除功能:

removeFirst()

removeLast()

获取功能:

getFirst()

getLast()

 

Vector:

底层数据结构是数组,查询快,增删慢,线程安全,同步,执行效率低

特有功能:

添加:

addElement(Objecte);

获取向量的组件:

Enurmeration<E> elements();

两个方法:

hasMoerElement()

nextElement();

Vector集合和后面将的IO流合并流(将很多个输入流串联起来):SequenceInputStream

Set集合:元素唯一的

HashSet,TreeSet(重点)

TreeSet:

自然排序

比较器排序

泛型:

格式:<数据类型>:只能是引用类型

好处:

将运行时期异常提前到了编译时期

解决黄色警告线问题

获取数据的时候不用强制类型转换了

提高程序的安全性

       泛型:通常情况下在集合中使用比较多,可以定义在类上,方法上,接口上等等;

 定义在方法上 :public <T>  void方法名(T t){...}

泛型定义在接口上比较多!

泛型的通配符:

<?>:表示任意类型,包括Object类型以及任意的Java

<? extends E>:向下限定,E及其子类

<? super E>:向上限定,E及其父类

 

Jdk7以后,创建集合对象的时候,后面出现:泛型推断:前后类型保持一致:

ArrayList<Student>  array = new ArrayList<Student>() ;

 

增强for循环:

增强for循环是用来替代迭代器的,书写格式简单,并且代码量少!

弊端:数组或者集合的对象的不能为null,否则会出现空指针异常!

遵循一个原则:

Java语言中,只要是对象,那么一定要给对象做非空判断,防止出现该异常!

格式:

for(数组或者集合中数据类型 变量名:数组或者集合对象){

输出变量名即可!

}

静态导入:

导入到方法(静态方法)的级别:

格式:import static java.lang.Math.abs;

可以在代码中不用前缀,直接去写.

main(){

Data:java.util.Date

java.sql.Date

java.util.Date d = new Date() ;

}

Js:有一个for-in语句:

for(var变量名: 对象名){

 

}

 

 

DAY15

1  Set接口:Set集合继承自Collection集合

 Set:底层数据结构是一个哈希表,能保证元素是唯一的,元素不重复!

它通过它的子实现了HashSet集合去实例化,HashSet集合底层是HashMap集合的实例!

 需求:Set集合存储字符串元素并遍历

import java.util.HashSet;

import java.util.Set;

public class SetDemo {

public static void main(String[] args) {

//创建Set集合对象

Set<String> set = new HashSet<String>() ;

//添加元素

set.add("hello");

set.add("java") ;

set.add("java") ;

set.add("world") ;

set.add("world") ;

set.add("world") ;

//增强for遍历

for(String s :set){

System.out.println(s);

}

}

}

2 hashcode

public class HashCodeDemo {

public static void main(String[] args) {

System.out.println("hello".hashCode());

System.out.println("hello".hashCode());

System.out.println("world".hashCode());

System.out.println("world".hashCode());

/**

 * 99162322

99162322

113318802

113318802

 */

}

}

3 需求:使用HashSet集合存储自定义对象并遍历

  List集合和Set集合的区别?

  Set:元素是唯一的,无序性(存储和取出不一致)

  List:元素可以重复,有序性(存储和取出一致)

 由于现在是自定义对象:在当前自定义对象的类中没有重写两个方法

  hashCodeequals()方法;HashSet底层是依赖于这两个实现来保证元素的唯一性!

public class HashSetDemo {

public static void main(String[] args) {

//创建一个HashSet集合对象

HashSet<Student> hs = new HashSet<Student>() ;

//创建学生对象

Student s1 = new Student("WDG", 24) ;

Student s2 = new Student("RNG, 25) ;

Student s3 = new Student("JHD", 26) ;

//给集合中添加学生对象

hs.add(s1) ;

hs.add(s2) ;

hs.add(s3) ;;

//增强for遍历

for(Student s : hs){

System.out.println(s.getName()+"---"+s.getAge());

}

}

}

4

  Set集合的子实现类:

  此类实现 Set接口,由哈希表(实际上是一个 HashMap实例)支持。它不保证 set的迭代顺序;

HashSet集合的add()方法,底层是依赖于双列集合HashMap<K,V>put(K key,V value)来实现的

  put(K key,V value):

 底层又依赖于HashCode()equals()方法,传递添加元素的时候,首先判断的是

 每一个元素对应的HashCode值是否一样,如果HashCode值一样,还比较他们的equals()方法,由于现在集合存储的是String类型,String类型本身重写了equals()方法,所以,默认比较的是内容是否相同,如果内容相同,这里最终返回的就是第一次存储的那个元素,由这两个方法保证元素唯一性!

import java.io.Serializable;

import java.util.HashSet;

public class SetDemo implements Serializable{

//private int num ;//setDemo.class固定id=100

 transient int num ;

public static void main(String[] args) {

//创建HashSet集合对象

HashSet<String> hs = new HashSet<String>();

//给该集合中添加元素

hs.add("hello") ;

hs.add("world") ;

hs.add("world") ;

hs.add("Java") ;

hs.add("Java") ;

//遍历

for(String s :hs){

System.out.println(s);

}

}

}

5具有可预知迭代顺序的Set 接口的哈希表和链接列表实现。

LinkedHashSet集合:

由哈希表保证元素的唯一性

由链接列表来保证元素的有序性!

 import java.util.LinkedHashSet;

public class LinkedHashSetDemo {

public static void main(String[] args) {

//创建LinkedHashSet集合对象

LinkedHashSet<String> link = new LinkedHashSet<String>();

//给集合中添加元素

link.add("hello") ;

link.add("world") ;

link.add("world") ;

link.add("Java") ;

link.add("Java") ;

link.add("JavaWeb") ;

link.add("JavaWeb") ;

//遍历集合

for(String s: link){

System.out.println(s);

}

}

}

 

6 TreeSet:Set集合中的一个重点

 TreeSet集合底层是依赖于TreeMap的实例,TreeMap<K,V>是依赖于红黑树结构实现的

分两种:

自然排序:

比较器排序

这种排序的使用取决于开发者是用什么样的构造方法

 TreeSet存储Integer类型添加以下元素

 20,18,23,22,17,24,19,18,24

import java.util.TreeSet

public class TreeSetDemo {

public static void main(String[] args){

//throw new IOException();

//创建TreeSet集合对象

//构造方法:

//public TreeSet():无参构造:根据其元素的自然顺序进行排序

//publict TreeSet(Comparaptr<E> com)

TreeSet<Integer> ts = new TreeSet<Integer>();//

//添加元素

//20,18,23,22,17,24,19,18,24

ts.add(20);// Integer i = Integer.valueOf(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) ;

//遍历这些元素

//增强for遍历

for(Integer i : ts){

System.out.print(i+ " ");//17 18 19 20 22 23 24 :唯一并且排序:自然排序(升序排序)

}

}

}

TreeSet集合存储自定义对象并遍历

实现了compareable接口,重写了comapreTo()方法,里面的逻辑是一个排序条件:

需求:

按照学生的年龄从小到大进行排序:主要条件

对于自定义对象什么情况下保证元素是唯一的

成员变量的值相同,认为是同一个元素

主要条件给定,需要分析次要条件

一个类中的元素想要自然排序,那么必须实现Compareable接口,实现compareTo(类名 对象名){}方法

按照正常存储对象的操作以及遍历对象出现了问题:

 类转换异常

* java.lang.ClassCastException: org.westos_04.Student cannot be cast to java.lang.Comparable

 

  需求:按照学生姓名长度从小到大进行排序

import java.util.TreeSet;

public class TreeSetDemo2 {

public static void main(String[] args) {

//创建TreeSet集合对象

TreeSet<Student> ts = new TreeSet<Student>() ;//

//创建学生对象

Student s1 = new Student("linqingxia", 28) ;

Student s2 = new Student("fengqingy", 28) ;

Student s3 = new Student("gaoyuanyuan", 27) ;

Student s4 = new Student("liushishi", 26) ;

Student s5 = new Student("wanglihong", 29) ;

Student s6 = new Student("zhangguorong", 30) ;

Student s7 = new Student("zhangguorong", 30) ;

ts.add(s1);

ts.add(s2);

ts.add(s3);

ts.add(s4);

ts.add(s5);

ts.add(s6);

ts.add(s7);

//遍历

for(Student s : ts){

System.out.println(s.getName()+"---"+s.getAge());

}

}

}

 

 

//MyComparatprComparator接口的子实现类

import java.util.Comparator;

public class MyComparator implements Comparator<Student> {

public int compare(Student s1, Student s2) {

//return 0;

//int num = this.name.lengt()-s.name.length();

//this--:s1

//s---:s2

int num = s1.getName().length() - s2.getName().length() ;

//次要条件:姓名长度一样,还要比较姓名的内容是否一样

int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;

//姓名长度和内容都一样,还需比较两个人的年龄是否一样

int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;

return num3 ;

}

}

  //元素唯一性:取决返回值是否为0

 要使用TreeSet集合的比较器排序:

依赖于构造方法:

public TreeSet(Comparator<E> comparator)

两种方式实现比较器排序:

Comparator接口作为形式参数进行传递,需要该接口的子实现类对象

import java.util.Comparator;

import java.util.TreeSet

public class TreeSetDemo {

public static void main(String[] args) {

//创建TreeSet集合使用比较器进行给元素进行排序

//public TreeSet(Comparator<E> comparator):有参构造

//方式1:自定义一个类,类实现Comparator接口,作为子实现类

//方式2:可以使用接口的匿名内部类来实现:

/**

  格式

  new接口名或者类名(){

 重写方法() ;

  }

 */

//TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;

TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

public int compare(Student s1, Student s2) {

//return 0;

int num = s1.getName().length() - s2.getName().length() ;

//次要条件:姓名长度一样,还要比较姓名的内容是否一样

int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;

//姓名长度和内容都一样,还需比较两个人的年龄是否一样

int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;

return num3 ;

}

}) ;

//创建学生对象

Student s1 = new Student("gaoyuanyan", 27) ;

Student s2 = new Student("liushishi", 22);

Student s3 = new Student("fengqingy", 23) ;

Student s4 = new Student("wuqilong", 35) ;

Student s5 = new Student("gaoyuanyuan",27) ;

Student s6 = new Student("zhangguorong",29) ;

Student s7 = new Student("gaoyuanyuan",26) ;

//添加元素

ts.add(s1) ;

ts.add(s2) ;

ts.add(s3) ;

ts.add(s4) ;

ts.add(s5) ;

ts.add(s6) ;

ts.add(s7) ;

//增强for遍历

for(Student s : ts){

System.out.println(s.getName()+"----"+s.getAge());

}

}

}

 

7

  Collection集合中关于:toString()方法的源码

  如果在一个类中没有找到该方法,继续往它的父类中找;


import java.util.ArrayList;

import java.util.Collection;

import java.util.Iterator;

public String toString() {

        Iterator<E> it = iterator();//this.iterator() ;

        if (! it.hasNext())    //首先判断迭代器是否由下一个可以跌倒的元素

            return "[]";

//迭代器中有可以遍历元素

        StringBuilder sb = new StringBuilder();//创建了一个字符串缓冲区

        sb.append('[');

        for (;;) {

            E e = it.next(); //获取元素

            sb.append(e == this ? "(this Collection)" : e);

            if (! it.hasNext())//最终如果集合中没有可以迭代(遍历)的元素

                return sb.append(']').toString();//拼接右中括号,转换String类型

            sb.append(',').append(' '); //中间每一个元素拼接逗号和空格

        }

    }

 

public class CollectionDemo {

public static void main(String[] args) {

//创建Collection集合对象:

Collection<String> c = new ArrayList<String>() ;

=//添加元素

c.add("hello") ;

c.add("world") ;

c.add("Java") ;

System.out.println(c);

}

}//    [hello, world, Java]

课堂练习:

  键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台

 1)创建一个学生类,提供姓名,语文,数学,英语这个成员变量

 2)创建TreeSet集合对象:TreeSet<Student>(Comparator<Student> com)

 3)分析条件:主要条件:总分从高到低

次要条件:总分相同,语文..

4)键盘录入5个学生:for循环

5)输出

import java.util.Comparator;

import java.util.Scanner;

import java.util.TreeSet;

public class TreeSetTest {

public static void main(String[] args) {

//创建TreeSet集合对象,使用有参构造

//比较器排序匿名内部类的方式

TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

public int compare(Student s1, Student s2) {

//主要条件:总分从高到到第进行排序

int num = s2.getSum() - s1.getSum();

//总分相同,不一定语文成绩相同,比较语文成绩

int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;

//总分相同,语文成绩相同,比较数学成绩

int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;

//总分相同,语文成绩相同,数学相同,比较英语

int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;

//总分以及各科成绩都相同,不一定是同一个人,姓名内容是否相同

int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName())

: num4;

return num5;

}

});

System.out.println("录入学生信息开始:");

//键盘录入5个学生的信息,姓名,语文成绩,数学成绩,英语成绩

for (int x = 1; x <= 5; x++) {

//创建键盘录入对象

//为了方便录入数据,数据类型都使用String类型接收

Scanner sc = new Scanner(System.in);

System.out.println("请输入第" + x + "个学生的姓名:");

String name = sc.nextLine();

System.out.println("请输入第" + x + "个学生的语文成绩:");

String chineseString = sc.nextLine();

System.out.println("请输入第" + x + "个学生的数学成绩:");

String mathString = sc.nextLine();

System.out.println("请输入第" + x + "个学生的英语成绩:");

String englishString = sc.nextLine();

//创建一个学生对象,把这些信息封装到学生对象中

Student s = new Student();

s.setName(name);

s.setChinese(Integer.parseInt(chineseString));

s.setMath(Integer.parseInt(mathString));

s.setEnglish(Integer.parseInt(englishString));

//将学生对象添加到集合中

ts.add(s);

}

System.out.println("学生信息录入结束:");

System.out.println("学生信息总分从高到底排列数学如下:");

System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩");

 

//增强for遍历集合

for (Student s : ts) {

System.out.println(s.getName() + "\t" + s.getChinese() + "\t"

+ s.getMath() + "\t" + s.getEnglish());

}

}

}

8 Random

import java.util.Random;

Random:产生一个随机数的类:

构造方式:

public Random()创建一个新的随机数生成器:默认种子不给定long类型的时间毫秒值

成员方法:

public int nextInt():由随机数生成器调用这个方法,随机数的范围在int类型的范围之内

public int nextInt(int n):生成随机数的范围:[0,n):使用比较多

import java.util.Random;

public class RandomDemo {

public static void main(String[] args) {

//创建一个随机数生成器

Random r = new Random();

for(int x = 0 ; x <10 ; x ++){

//随机数生成器:r调用他们的成员方法

//int number = r.nextInt() ;

//public int nextInt(int n):生成随机数的范围:[0,n)

int number = r.nextInt(20) +1;

System.out.println(number);

}

}

}

课堂练习

 获取101-20之间的随机数,要求不能重复

 数组来操作,数组弊端,长度固定,使用集合存储

分析

 1)创建一个随机数生成器:Random类来创建

 2)使用ArrayList集合去存储,数据类型:Integer

 3)定义中统计变量count,

 4)循环判断如果统计变量小于10

通过随机数生成器获取1-20之间的数据

判断集合中是否包含这些随机数,如果不包含,猜添加到集合中

 5)遍历集合,拿到元素

import java.util.ArrayList;

import java.util.Random;

 

public class Test {

public static void main(String[] args) {

//1)创建一个随机数生成器

Random r = new Random();

//2)创建ArrayList集合,类型Integer

ArrayList<Integer> array = new ArrayList<Integer>() ;

//3)定义统计遍历

int count = 0 ;

//4)循环判断

while(count <10){

//通过随机数生成器获取:1-20之间的随机数

int number = r.nextInt(20) +1;

//有随机数了,还需要判断集合中是否包含这些随机数

if(!array.contains(number)){

//如果不包含,才添加到集合中

array.add(number) ;

count ++ ;

}

}

//遍历集合:增强for

for(Integer i : array){

System.out.println(i);

}

}

}

 

 

 

综合案例

用户登陆注册案例:

符号面向对象分析特点:

1)当前需求中有哪些类?

2)知道某些类,这些类中有什么东西

3)这些类和类之间有什么关系

1)有哪些类:

用户类

用户的基本信息描述:

在这个基本描述类中提供:成员:username password ,提供set()/get()方法

具体的划分:

按照功能划分:

注册功能

登陆功能

用户操作的接口:

注册();登陆();

用户操作的接口实现类:

 注册(){..}

 登陆(){..}

用户要进行操作:

注册

登陆

测试类:

Usertest:用户测试类:

用户类和测试类:

在测试类中需要创建用户类对象,来操作登陆和注册功能

经常会按照功能划分,模块划分:

1)先按照功能划分,在按照模块划分

2)先模块划分,功能划分.

给每一个包命名的时候:

用户的描述类:user

:公司域名.entity;实体类

org.westos.entity;

用户操作的接口:

:公司域名.dao:里面放的 是接口

   org.westos.dao :接口层

用户操作接口的实现类:

:

org.westos.dao.impl:业务逻辑层:接口子实现类

测试类:

:

org.westos.test:需要针对注册或者的登陆进行测试

1  //用户的实体类

public class User {

//成员变量

private String username;

private String password;

public User() {

super();

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

import org.wesots.entity.User;

 // 用户的操作接口

public interface UserDao {

/**

  该方法是用户登陆功能

  @param username

  被传递的用户名

  @param password

  需要被传递的用户密码

  @return

  返回值表示最终登陆是否成功

 */

public abstract boolean isLogin(String username,String password) ;

/**

 该方法表示是用户注册功能

 @param user

表示需要注册的用户

 */

public abstract void regist(User user) ;

}

public void setPassword(String password) {

this.password = password;

}

}

 

/**

 这是用户操作的接口实现类:业务逻辑层

 集合版

 */

import java.util.ArrayList;

import org.wesots.entity.User;

import org.westos.dao.UserDao;

public class UserDaoImpl implements UserDao {

//为了多个功能使用这个集合中的用户,将集合的对象定义到成员变量中

//为了不让外界修改集合,所以private修饰

//将集合对象共享:注册和登陆使用的同一个集合对象

private static ArrayList<User> array = new ArrayList<User>() ;

//登陆功能

public boolean isLogin(String username, String password) {

//登陆,需要将注册的时候用户全都遍历出来,所以创建ArrayList集合

//假设:定义标记,用户登陆不成成功

boolean flag = false ;

//需要遍历集合获取集合中的每一个用户

for(User u :array){

//获取到每一个用户对象:u

//判断

if(u.getUsername().equals(username) && u.getPassword().equals(password)){

//修改标记

flag = true ;

break ;

}

}

return flag ;

}

//注册功能

public void regist(User user) {

//由于有很多用户,需要将用户存储到集合中,需要创建一个集合

//ArrayList<User> array = new ArrayList<User>() ;

//将用户存储到集合中

array.add(user) ;

}

 

}

 

 

 

//猜数字游戏的类

import java.util.Scanner;

public class GuessNumberGame {

//无参构造私有

private GuessNumberGame() {

}

//静态功能

public static void start(){

//产生一个随机数

int number = (int) (Math.random()*100 +1) ;

//定义一个统计变量

int count = 0 ;

//多次循环

while(true){

//创建键盘录入对象

Scanner sc = new Scanner(System.in) ;

System.out.println("请你输入一个数据:");

int guessNumber = sc.nextInt() ;

//统计变量++

count ++ ;

if(guessNumber>number){

System.out.println("你要猜的数据"+guessNumber+"大了");

}else if(guessNumber <number){

System.out.println("你要猜的数据"+guessNumber+"小了");

}else{

System.out.println("恭喜您"+count+"次猜中了");

break ;

}

}

}

}

 

 用户的测试类

 注意事项:

1)登陆功能和注册功能使用的是同一个集合,将集合的对象的数据共享,应该用static

    2):登陆成功应该退出界面,

现在使用switch语句,遇见break,只是结束switch语句并不能结束循环语句----->

public class UserTest {

public static void main(String[] args) {

//为了能够回来,加入while循环

while(true){

//给出选择的界面

System.out.println("-------------------欢迎光临------------------------");

System.out.println("请选择:");

System.out.println("1  登陆");

System.out.println("2  注册");

System.out.println("3  退出");

//创建键盘录入对象

Scanner sc = new Scanner(System.in) ;

//根据不同的选择给出界面,简单分析下

//为了方便数据的录入,就是用String类型接收

String choiceString = sc.nextLine() ;

//由于用户都需要调用登陆和注册功能,通过接口多态,所以将该用户操作的登陆对象定义到switch语句外面

UserDao ud  = new UserDaoImpl() ;

//简单分析:就可以使用switch语句

switch(choiceString){

case "1":

//登陆界面

System.out.println("------------登陆界面--------------");

System.out.println("请输入用户名:");

String username = sc.nextLine() ;

System.out.println("请您输入密码:");

String password = sc.nextLine() ;

//需要调用登陆功能

//UserDao ud = new UserDaoImpl() ;

boolean flag = ud.isLogin(username, password) ;

//判断

if(flag){

System.out.println("登陆成功,开始玩游戏吗?");

System.out.println("玩游戏吗?y/n");

while(true){

String resultString = sc.nextLine();

if(resultString.equalsIgnoreCase("y")){

//开始玩游戏

GuessNumberGame.start() ;

System.out.println("你还玩吗?y/n");

}else{

break ;

}

}

System.out.println("谢谢使用,下次再来...");

//break ;//遇见break,只是结束switch语句并不能结束循环语句

System.exit(0) ;

}else{

System.out.println("用户名或者密码错误,请重新输入....");

}

break ;

case "2":

//注册界面

System.out.println("------------注册界面--------------");

System.out.println("请您输入用户名:");

String newUserName = sc.nextLine() ;

System.out.println("请您输入密码:");

String newPassword = sc.nextLine() ;

//将用户名和密码封装到用户对象中

User u = new User() ;

u.setUsername(newUserName) ;

u.setPassword(newPassword) ;

//调用注册的功能:

//接口多态:

//UserDao ud = new UserDaoImpl() ;

ud.regist(u) ;

System.out.println("注册成功..");

break ;

case "3":

default:

System.out.println("谢谢使用,下次再来!");

System.exit(0) ;

break ;

}

}

}

原创粉丝点击