[2017.11.12]Set&HashSet&LinkedHashSet&TreeSet&模拟用户

本文深入解析了Java中的Set集合,包括Set接口的特点、底层实现原理、不同Set实现类(如HashSet、LinkedHashSet、TreeSet)的功能特性及应用场景,并通过具体代码示例展示了如何使用这些集合存储与遍历数据。
摘要由CSDN通过智能技术生成

Set集合

1.Set接口:Set集合继承自Collection集合
Set:底层数据结构是一个哈希表,能保证元素是唯一的,元素不重复!
它通过它的子实现了HashSet集合去实例化,HashSet集合底层是HashMap集合的实例

2.演示:Set集合存储字符串元素并遍历

public 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);
        }
    }
}

HashSet集合

1.Set集合的子实现类:
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;
特别是它不保证该顺序恒久不变.

2.看源码
HashSet集合的add()方法,底层是依赖于双列集合HashMap

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);
        }
    }
}

4.HashSet集合的add()方法的源码:

interface Collection{}
interface Set Extends Collection{

}

class HashSet<E> implements Set<E>{
      private transient HashMap<E,Object> map;


       //HashSet集合的无参构造方法
       public HashSet() {
            map = new HashMap<>();
         }


         //HashSet集合的添加功能:
          public boolean add(E e) {//"hello","world","world"
             return map.put(e, PRESENT)==null;//"hello","world","world"= e
         }
}

class HashMap<K,V> implements Map<K,V>{

    //HashMap集合添加元素的功能
    public V put(K key, V value) {//k="hello","world"
        if (table == EMPTY_TABLE) {//table:判断哈希表示==空表
            inflateTable(threshold);
        }
        if (key == null)//元素是空
            return putForNullKey(value);
        int hash = hash(key);//携带当前HashSet集合中的元素:"hello","world","world" :第一次的world和第二次world返回到HashCode值一样
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {//for循环:遍历键值对象的(Map集合遍历)
            Object k;
            if (ase.hh == hash && ((k = e.key) == key || key.equals(k))) {
            //e:每一个元素:要判断他们的hashCode值是否一样,如果hashCode值一样还要判断他们的equals()方法,而对于String类型来说,底层已经重写了
            Object中的equals()方法,所以比较多是内容是否相同
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue; //hashCode()值一样,在比较内容是否相同,(如果相同),直接返回第一次存储的"world"
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }


    //hash()方法
     final int hash(Object k) {"hello","world","world
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();//每一个元素都要调用:hashCode();是Object类中的方法

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
}


//创建HashSet集合对象
        HashSet<String> hs = new HashSet<String>();

        //给该集合中添加元素
        hs.add("hello") ;
        hs.add("world") ;
        hs.add("world") ;
        hs.add("Java") ;
        hs.add("Java") ;

5.List集合和Set集合的区别?
Set:元素是唯一的,无序性(存储和取出不一致)
List:元素可以重复,有序性(存储和取出一致)

由于现在是自定义对象:在当前自定义对象的类中没有重写两个方法
hashCode和equals()方法;HashSet底层是依赖于这两个实现来保证元素的唯一性

6.演示:使用HashSet集合存储自定义对象并遍历

import java.util.HashSet;

public class HashSetDemo {

    public static void main(String[] args) {

        //创建一个HashSet集合对象
        HashSet<Student> hs = new HashSet<Student>() ;

        //创建学生对象
        Student s1 = new Student("高圆圆", 27) ;
        Student s2 = new Student("张三", 25) ;
        Student s3 = new Student("唐嫣", 26) ;
        Student s4 = new Student("邓超", 29) ;
        Student s5 = new Student("胡歌", 23) ;
        Student s6 = new Student("高圆圆", 27) ;

        //给集合中添加学生对象
        hs.add(s1) ;
        hs.add(s2) ;
        hs.add(s3) ;
        hs.add(s4) ;
        hs.add(s5) ;
        hs.add(s6) ;

        //增强for遍历
        for(Student s : hs){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}

6.Set集合的子实现类:
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;
特别是它不保证该顺序恒久不变。

看源码:
HashSet集合的add()方法,底层是依赖于双列集合HashMap

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);
        }
    }
}
//学生类
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() {
        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;
        Student other = (Student) 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;
    }


}

LinkedHashSet集合

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

2.LinkedHashSet集合:
由哈希表保证元素的唯一性
由链接列表来保证元素的有序性!

3.演示:

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);
        }
    }
}

TreeSet集合

1.TreeSet:Set集合中的一个重点
TreeSet集合底层是依赖于TreeMap的实例,而TreeMap

/**
 * 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 :唯一并且排序:自然排序(升序排序)
        }
    }
}

3.TreeSet集合存储自定义对象并遍历
实现了compareable接口,重写了comapreTo()方法,里面的逻辑是一个排序条件:

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

5.按照正常存储对象的操作以及遍历对象出现了问题:
类转换异常
java.lang.ClassCastException: org.westos_04.Student cannot be cast to java.lang.Comparable

6.演示:

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());
        }
    }   
}
package org.westos_04;

//对于TreeSet集合存储自定义对象必须实现一个接口:compareable接口
public class Student implements Comparable<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;
    }



    //重写了compareTo()方法
    @Override
    public int compareTo(Student s) {
//      return 0;
        //排序的代码了,需要定义排序的条件
        //主要条件:按照学生的年龄从小到大进行排序
        int num =s.age - this.age ;//年龄从大到小 
//      return num ;
        //当num==0认为年龄一样,年龄一样,不代表姓名的的内容是否相同,需要自己给出次要条件
        int num2 = num==0 ? this.name.compareTo(s.name): num ;
        return num2 ;
    }


}

9.TreeSet集合的add()方法的源码:

interface Collection{
}
interface Set extends Collection{
}

class TreeSet implements Set{

    private transient NavigableMap<E,Object> m;

    //无参构造方法
     TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

     public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
}

class TreeMap<K,V> implements NavigableMap<K,V>{

        private transient int modCount = 0; 该变量不会被序列化

    //Map集合中添加元素的方法
    public V put(K key, V value) {///20,18,23,22,17,24,19,18,24 = key 
        Entry<K,V> t = root;//root=第一次存储的20这个元素
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;//父节点==t==20
        // split comparator and comparable paths
        //比较器排序
        Comparator<? super K> cpr = comparator;//this.comparaptr;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);//t.key==通过根节点和后面依次传来的元素进行比较
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);//键值对象不能为null
        }
        else {
        //自然排序:由于创建TreeSet集合对象TreeSet():无参构造形式
            if (key == null)//key=需要存储的元素://20,18,23,22,17,24,19,18,24--->Integer类型
                throw new NullPointerException();//一定空指针异常
            Comparable<? super K> k = (Comparable<? super K>) key; //声明了一个接口对象:Comparable接口对象 :this.key
            do {
                parent = t;//20
                cmp = k.compareTo(t.key);t.key==通过根节点和后面依次传来的元素进行比较
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }

        //存储元素
        Entry<K,V> e = new Entry<>(key, value, parent); //创建新的键值对象
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;     //将元素分别依次取出来
        return null;
    }
}

结论:对于TreeSet集合要实现自然排序,那么该集合该集合中存储自定义类型必须实现一个接口:Comparable,并且重写该接口中的compareTo()方法
使用TreeSet集合存储自定义对象并遍历

10.演示:

import java.util.TreeSet;

/**
 * 需求:按照学生姓名长度从小到大进行排序
 * @author Apple
 */
public class TreeSetTest {

    public static void main(String[] args) {

        //创建TreeSet集合对象
        TreeSet<Student> ts = new TreeSet<Student>() ;

        //创建几个学生对象
        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(Student s : ts){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}
//如果一个类中的元素要实现自然排序,就必须实现Compareable接口
public class Student implements Comparable<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;
    }


    //元素唯一性:取决返回值是否为0
    @Override
    public int compareTo(Student s) {
//      return 0;
        //主要条件按照学生姓名长度从小到大进行排序
        int num = this.name.length() - s.name.length() ;

        //次要条件:
        //姓名长度一样,能代表姓名的内容一样吗?
        //在增加一个条件:姓名长度一样,还需需要比较内容是否一样
        int num2 = num==0?this.name.compareTo(s.name) :num ;

        //次要条件:姓名长度一样,内容也一样,不一定年龄一样,所以还需要比较年龄是否相同;

        int num3 = num2==0? this.age - s.age : num2 ;
        return  num3 ;
    }



}

11.演示:

import java.util.Comparator;
import java.util.TreeSet;


/**
 * 需求:按照学生姓名长度从小到大进行排序
 * 
 * //元素唯一性:取决返回值是否为0
 * 要使用TreeSet集合的比较器排序:
 *  依赖于构造方法:
 *          public TreeSet(Comparator<E> comparator)
 * 
 *          两种方式实现比较器排序:
 *                  Comparator接口作为形式参数进行传递,需要该接口的子实现类对象
 */
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>() {

            @Override
            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());
        }
    }
}
package org.westos_06;

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;
    }




}
import java.util.Comparator;

//MyComparatpr是Comparator接口的子实现类
public class MyComparator implements Comparator<Student> {

    @Override
    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 ;
    }

}

12.演示:

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

/**
 * 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
 *  
 * 分析:
 *      1)创建一个学生类,提供姓名,语文,数学,英语这个成员变量
 *      2)创建TreeSet集合对象:TreeSet<Student>(Comparator<Student> com)
 *      3)分析条件:主要条件:总分从高到低
 *              次要条件:总分相同,语文..
 *      4)键盘录入5个学生:for循环
 *      5)输出
 * @author Apple
 */
public class TreeSetTest {

    public static void main(String[] args) {

        // 创建TreeSet集合对象,使用有参构造
        // 比较器排序匿名内部类的方式
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

            @Override
            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());
        }
    }
}
public class Student {

    private String name ;//姓名
    private int chinese ;//语文
    private int math ;//数学
    private int english;//英语
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Student(String name, int chinese, int math, int english) {
        super();
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public int getChinese() {
        return chinese;
    }
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
    public int getMath() {
        return math;
    }
    public void setMath(int math) {
        this.math = math;
    }
    public int getEnglish() {
        return english;
    }
    public void setEnglish(int english) {
        this.english = english;
    }


    //总分的方法
    public int getSum(){
        return this.chinese + this.math+this.english ;
    }

}

13.Collection集合中关于:toString()方法的源码
如果在一个类中没有找到该方法,继续往它的父类中找

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(' '); //中间每一个元素拼接逗号和空格
        }
    }
    [hello, world, Java]

14.演示:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

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);
    }
}

使用集合来模拟用户登陆注册

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

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

3.成员方法:
public int nextInt():由随机数生成器调用这个方法,随机数的范围在int类型的范围之内
public int nextInt(int n):生成随机数的范围:[0,n):使用比较多

4.演示:

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);

        }
    }
}

5.演示:

package org.westos_random;

import java.util.ArrayList;
import java.util.Random;

/**
 * 获取10个1-20之间的随机数,要求不能重复
 * 
 * 数组来操作,数组弊端,长度固定,使用集合存储
 * 
 * 分析
 *      1)创建一个随机数生成器:Random类来创建
 *      2)使用ArrayList集合去存储,数据类型:Integer
 *      3)定义中统计变量count,
 *      4)循环判断如果统计变量小于10
 *          通过随机数生成器获取1-20之间的数据
 *          判断集合中是否包含这些随机数,如果不包含,猜添加到集合中
 *          count ++
 *      5)遍历集合,拿到元素
 * @author Apple
 */
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.

如何分析需求:
    用户登陆注册案例:
        符号面向对象分析特点:
                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:需要针对注册或者的登陆进行测试

2.用户的实体类

package org.wesots.entity;

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;
    }

    public void setPassword(String password) {
        this.password = password;
    }


}

3.用户的操作接口

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) ;
}

4.用户操作的接口实现类:业务逻辑层(集合版)

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>() ;

    //登陆功能
    @Override
    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 ;

    }


    //注册功能
    @Override
    public void regist(User user) {
        //由于有很多用户,需要将用户存储到集合中,需要创建一个集合
//      ArrayList<User> array = new ArrayList<User>() ;
        //将用户存储到集合中
        array.add(user) ;
    }

}

5.用户的测试类

import java.util.Scanner;

import org.wesots.entity.User;
import org.westos.dao.UserDao;
import org.westos.dao.impl.UserDaoImpl;
import org.westos.game.GuessNumberGame;

/** 
 * 注意事项:
 *      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 ;
            }
        }

    }
}

6.猜数字游戏的类

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 ;
            }
        }


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值