Java学习笔记(二)

1. Java抽象类:

  • 抽象类和抽象方法都必须用abstract修饰,而且抽象方法不能有方法体
  • 抽象类不能被实例化,即便这个抽象类没有包含抽象方法
  • 抽象类的构造器不能用于创建实例,只能用于被其子类调用
  • 含有抽象方法的类(包括直接定义一个抽象方法;继承了一个抽象父类但没有完全实现父类包含的抽象方法;以及实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义为抽象类
  • 注意:
    • abstract修饰的方法只能被子类复写并实现,而final修饰的方法不允许子类复写,故abstract和final永远不要一起使用
    • abstract不能用于修饰属性和局部变量,也不能用于修饰构造器
  • abstract也不能与private同时使用(private修饰的变量不会被子类重写)

2. 局部内部类、变量只在方法内有效,它的上一级程序单元是方法而不是类,故不能用static和访问控制权限符修饰


3. HashSet:

  •  1 import java.util.*;
     2
     3 //A类的equals方法总是返回ture,但没有重写切hashCode方法
     4 class A{
     5     public boolean equals(Object obj){
     6         return true;
     7     }
     8 }
     9
    10 //B类的hashCode方法总是返回1,但没有重写其equals方法
    11 class B{
    12     public int hashCode(){
    13         return 1;
    14     }
    15 }
    16
    17 //C类的hashCode总是返回2,有重写其equals方法
    18 class C{
    19     public int hashCode(){
    20         return 2;
    21     }
    22
    23     public boolean equals(Object obj){
    24         return true;
    25     }
    26 }
    27
    28 public class TestSet
    29 {
    30     public static void main(String[] args)
    31     {
    32         HashSet books = new HashSet();
    33         books.add(new A());
    34         books.add(new A());
    35         books.add(new B());
    36         books.add(new B());
    37         books.add(new C());
    38         books.add(new C());
    39         System.out.println(books);
    40     }
    41 }
    42
    43
    44 /*
    45 [[email protected], [email protected], [email protected], [email protected], [email protected]]
    46 请按任意键继续. . .
    47 */
  • HashSet通过同时判断equals和hashCode来区别重复元素(如果equals和hashCode对比返回都是true, 则为重复元素)
  • HashSet储存是无序的,是根据hashCode的值来对应一个储存位置来存储元素(其实hashCode就相当于HashSet的索引,它通过这个索引来找到对应元素,速度很快)
  • 重写hashCode的规则:
    • 当两个对象通过equals方法比较返回true时,这两个对象的hashCode的值应该相等
    • 对象中用作equals比较标准的属性,都应该用来计算hashCode的值
  • 向HashSet中添加一个个可变对象,并改变其值可能会产生的问题:
    •  1 import java.util.*;
       2 class R
       3 {
       4     int count;
       5     public R(int count){
       6         this.count = count;
       7     }
       8
       9     public String toString(){
      10         return "R(count 属性 :" + count + " )";
      11     }
      12
      13     public boolean equals(Object obj){
      14         if(obj instanceof R){
      15             R r = (R)obj;
      16             if(r.count == this.count){
      17                 return true;
      18             }
      19         }
      20         return false;
      21     }
      22
      23     public int hashCode(){
      24         return this.count;
      25     }
      26 }
      27
      28
      29 public class TestHashSet
      30 {
      31     public static void main(String[] args)
      32     {
      33         HashSet hs = new HashSet();
      34         hs.add(new R(5));
      35         hs.add(new R(-3));
      36         hs.add(new R(9));
      37         hs.add(new R(253));
      38
      39         //打印HashSet集合
      40         System.out.println(hs);
      41
      42         //取出第一个元素
      43         Iterator it = hs.iterator();
      44         it.next();
      45         R first = (R)it.next();
      46         //为第一个元素的count赋值
      47         first.count = -3;
      48
      49         //再次输出HashSet集合,集合有重复元素
      50         System.out.println(hs);
      51
      52         //删除count为-3的R对象
      53         hs.remove(new R(-3));
      54
      55         //可以看到被删除了一个R元素
      56         System.out.println(hs);
      57
      58         //输出false
      59         System.out.println("hs是否包含count为-3的R对象?" + hs.contains(new R(-3)));
      60         //输出false
      61         System.out.println("hs是否包含count为5的R对象?" + hs.contains(new R(5)));
      62     }
      63 }
      64
      65 /*
      66 [R(count 属性 :-3 ), R(count 属性 :5 ), R(count 属性 :9 ), R(count 属性 :253 )]
      67 [R(count 属性 :-3 ), R(count 属性 :-3 ), R(count 属性 :9 ), R(count 属性 :253 )]
      68 [R(count 属性 :-3 ), R(count 属性 :9 ), R(count 属性 :253 )]
      69 hs是否包含count为-3的R对象?false
      70 hs是否包含count为5的R对象?false
      71 请按任意键继续. . .
      72 */
    • 说明:
      • 第二个-3虽然值为-3,但它却是放在原来值为-5的位置,删除时不会被删除,而且这个时候equals和hashCode永远不能保持一致,之后这个HashSet的访问将会存在问题
    • 注意:当向HashSet中添加可变对象时,必须十分小心,如果修改HashSet集合中的对象,有可能导致该对象与集合中的其他对象相等,从而导致HashSet无法准确访问该对象

4. TreeSet(是SortedSet接口的唯一实现)

  • 自然排序:Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,实现了该接口就可以比较大小,常见类已经实现了该方法,TreeSet根据该方法来进行排序
  • 如果试图将一个对象添加进TreeSet,则该对象的类必须实现Comparable接口,否则程序将会抛出异常(向TreeSet里添加对象时,只有第一个元素可以不实现Comparable接口,但这不是一个好做法,当取出该元素是会抛出ClassCastException)
  • 向TreeSet里添加的也应该是同一类型的对象,否则也会抛出ClassCastException(实现compareTo(Object obj)方法时也应该将obj强制转换为相同类型来进行比较)
  • 判断重复元素的标准:
    • equals方法返回true
    • compareTo方法返回0
  • 如果两个对象的equals方法返回true,则应该保证compareTo方法返回0;

5. LinkedList

  •  1 import java.util.*;
     2
     3 public class TestLinkedList
     4 {
     5     public static void main(String[] args)
     6     {
     7         LinkedList books = new LinkedList();
     8         //将字符串元素加入队列的尾部
     9         books.offer("Robbin1");
    10         //将一个字符串元素入栈
    11         books.push("Robbin2");
    12         //将字符串元素添加到队列的头部
    13         books.offerFirst("Robbin3");
    14         for(int i = 0; i < books.size(); i++){
    15             System.out.println(books.get(i));
    16         }
    17
    18         //访问并不删除队列的第一个元素
    19         System.out.println(books.peekFirst());
    20         //访问并不删除队列的最后一个元素
    21         System.out.println(books.peekLast());
    22         //采用出栈的方式将第一个元素pop出队列
    23         System.out.println(books.pop());
    24         //下面输出将看到第一个元素被删除
    25         System.out.println(books);
    26         //访问并删除队列的最后一个元素
    27         System.out.println(books.pollLast());
    28         System.out.println(books);
    29     }
    30 }
    31
    32 /*
    33 Robbin3
    34 Robbin2
    35 Robbin1
    36 Robbin3
    37 Robbin1
    38 Robbin3
    39 [Robbin2, Robbin1]
    40 Robbin1
    41 [Robbin2]
    42 请按任意键继续. . .
    43 */
  • LinkedList兼备List,stack和双向队列的功能,一般与ArrayList没有太大性能上的差异,但在一些性能敏感的地方要注意选择
  • 关于List集合的建议:
    • 如果需要遍历List集合元素,对于ArrayList和vector集合,则应该使用随机访问方法(get)来遍历集合元素,这样性能更好。对于LinkedList集合,则应该采用迭代器(Iterator)来遍历集合元素;
    • 如果需要经常执行插入、删除操作来改变List集合的大小,则应该使用LinkedList集合而不是ArrayList。使用ArrayList、vector集合将需要重新分配内部数组大小,其时间开销常常是使用LinkedList的时间开销的几十倍,效果更差;
    • 如果有多条线程同时访问List集合中的元素,可以考录vector这个同步实现;

6. 操作集合的工具类

排序操作:

    •  1 import java.util.*;
       2 public class TestSort
       3 {
       4     public static void main(String[] args)
       5     {
       6         ArrayList nums = new ArrayList();
       7         nums.add(2);
       8         nums.add(-5);
       9         nums.add(3);
      10         nums.add(0);
      11         nums.add(1);
      12
      13         System.out.println(nums);
      14         //将List集合元素的次序反转
      15         Collections.reverse(nums);
      16         System.out.println(nums);
      17         //将List集合元素按自然排序排序
      18         Collections.sort(nums);
      19         System.out.println(nums);
      20         //将List集合元素按随机顺序排序
      21         Collections.shuffle(nums);
      22         //每次输出的次序不固定
      23         System.out.println(nums);
      24
      25     }
      26 }
      27
      28 /*
      29 输出结果:[2, -5, 3, 0, 1]
      30 [1, 0, 3, -5, 2]
      31 [-5, 0, 1, 2, 3]
      32 [2, 1, 0, 3, -5]
      33 请按任意键继续. . .
      34 */
    •   1 import java.util.*;
        2 import java.lang.reflect.Array;
        3 public class ShowHand
        4 {
        5     //定义该游戏最多支持几个玩家
        6     private final int PLAY_NUM = 5;
        7     //定义扑克牌的所有花色
        8     //下面是四个特殊字符,会在控制台打印出方块,草花, 红心,黑桃
        9     private String[] types = {"\4 ", "\5 ", "\3 ", "\6 "};
       10     private String[] values = {"2 ", "3 ", "4 ", "5 ", "6 ", "7 ", "8 ", "9 ", "10 ", "J ", "Q ", "K ", "A "};
       11
       12     //cards是一局游戏中剩下的扑克牌
       13     private List<String> cards = new LinkedList<String>();
       14     //定义所有玩家
       15     private String[] players = new String[PLAY_NUM];
       16     //所有玩家手上的扑克牌
       17     private List<String>[] playersCards = new List[PLAY_NUM];
       18
       19     /**
       20     * 初始化扑克牌,放入52张扑克牌,并且使用shuffle方法将他们按随机顺序排序
       21     */
       22     public void initCards(){
       23         for(int i = 0; i < types.length; i++){
       24             for(int j = 0; j < values.length; j++){
       25                 cards.add(types[i] + values[j]);
       26             }
       27         }
       28         //随机排序
       29         Collections.shuffle(cards);
       30
       31     }
       32
       33
       34     /**
       35     * 初始化玩家,为每个玩家分配用户名
       36     */
       37     public void initPlayer(String... names){
       38         if(names.length > PLAY_NUM || names.length < 2){
       39             //校检玩家数量,此时处理异常更合理
       40             System.out.println("玩家数量不对");
       41             return ;
       42         }else{
       43             //初始化玩家用户名
       44             for(int i = 0; i < names.length; i++){
       45                 players[i] = names[i];
       46             }
       47         }
       48     }
       49
       50     /**
       51     * 初始化玩家手上的扑克牌,开始游戏时每个玩家手上的扑克牌为空,
       52     * 程序使用一个长度为0的LinkedList表示。
       53     */
       54     public void initPlayerCards(){
       55         for(int i = 0; i < players.length; i++){
       56             if(players[i] != null && !players[i].equals("")){
       57                 playersCards[i] = new LinkedList<String>();
       58             }
       59         }
       60     }
       61
       62     /**
       63     * 输出全部扑克牌,该方法没有实际作用,仅用作测试
       64     */
       65     public void showAllCards(){
       66         for(String card : cards){
       67             System.out.println(card);
       68         }
       69     }
       70
       71     /**
       72     * 派扑克牌
       73     * @param first 最先派给谁
       74     */
       75     public void deliverCard(String first){
       76         //调用ArrayUtils工具类的search方法。查询出制定元素在数组中的索引
       77         //int firstPos = ArrayUtils.search(players, first);
       78         int firstPos = 0;
       79         //依次给位于该指定玩家之后的每个玩家派扑克牌
       80         for(int i = firstPos; i < PLAY_NUM; i++){
       81             if(players[i] != null){
       82                 playersCards[i].add(cards.get(0));
       83                 cards.remove(0);
       84             }
       85         }
       86         //依次给位于该指定玩家之前的每个玩家派扑克牌
       87         for(int i = 0; i < firstPos; i++){
       88             if(players[i] != null){
       89                 playersCards[i].add(cards.get(0));
       90                 cards.remove(0);
       91             }
       92         }
       93     }
       94
       95     /**
       96     * 输出玩家手上的扑克牌
       97     * 实现该方法时,应该控制每个玩家看不到别人的第一张牌, 但此处没有增加该功能
       98     */
       99     public void showPlayerCards(){
      100         for(int i = 0; i < PLAY_NUM; i++){
      101             //当玩家不为空时
      102             if(players[i] != null){
      103                 System.out.print(players[i] + " : ");
      104                 //便利玩家手上的牌
      105                 for(String card : playersCards[i]){
      106                     System.out.print(card + "\t");
      107                 }
      108                 System.out.print("\n");
      109             }
      110         }
      111     }
      112     public static void main(String[] args)
      113     {
      114         ShowHand sh = new ShowHand();
      115         sh.initPlayer("电脑玩家", "ME");
      116         sh.initCards();
      117         sh.initPlayerCards();
      118         //下面测试所有扑克牌,没有实际作用
      119         sh.showAllCards();
      120         System.out.println("---------------------------------------------------------------------");
      121         //下面从ME开始派牌
      122         sh.deliverCard("ME");
      123         sh.showPlayerCards();
      124
      125         sh.deliverCard("电脑玩家");
      126         sh.showPlayerCards();
      127     }
      128 }
      129
      130
      131 /*
      132  5
      133  2
      134  9
      135  6
      136  K
      137  K
      138  8
      139  7
      140  6
      141  8
      142  4
      143  6
      144  8
      145  A
      146  2
      147  2
      148  4
      149  3
      150  3
      151  J
      152  9
      153  A
      154  7
      155  10
      156  3
      157  Q
      158  6
      159  Q
      160  J
      161  9
      162  4
      163  A
      164  5
      165  4
      166  10
      167  K
      168  10
      169  8
      170  9
      171  10
      172  7
      173  Q
      174  A
      175  K
      176  J
      177  2
      178  5
      179  7
      180  Q
      181  5
      182  3
      183  J
      184 ---------------------------------------------------------------------
      185 电脑玩家 :  5
      186 ME :  2
      187 电脑玩家 :  5   9
      188 ME:  2         6
      189 请按任意键继续. . .
      190 */
    • 查找替换操作:
      • static int binarySearch (List list, Object key):使用二分法搜索指定List集合,以获得指定对象在List集合中的索引(如果该方法要能正常工作,必须保证List集合元素已经处于有序状态)
      • static Object max(Collection coll):更具元素的自然顺序,返回给定集合中的最大元素
      • static Object max(Collection coll, Comparator comp):根据指定Comparator产生的顺序,返回指定集合的最大元素
      • static Object min(Collection coll)
      • static Object min(Collection coll, Comparator comp)
      • static void fill(List list, Object obj):使用指定元素obj替换指定List集合中的所有元素
      • static int frequency(Collection c, Object o):返回指定List集合中的指定对象的元素数量
      • static int indexOfSubList(List source, List target):返回List对象在母List对象中第一次出现的位置索引;如果母List中没有出现这样的子List,则返回-1
      • static int lastIndexOfSubList(List source, List target)
      • static boolean replaceAll(List list, Object oldVal, Object newVal):使用一个新值newVal替换List对象所有的旧值oldVal
      •  1 import java.util.*;
         2 public class TestSearch
         3 {
         4     public static void main(String[] args)
         5     {
         6         ArrayList nums = new ArrayList();
         7         nums.add(2);
         8         nums.add(-5);
         9         nums.add(3);
        10         nums.add(0);
        11
        12         System.out.println(nums);
        13         //输出最大元素,将输出3
        14         System.out.println(Collections.max(nums));
        15         //输出最小元素,将输出-5
        16         System.out.println(Collections.min(nums));
        17         //将nums中的0用1来替代
        18         Collections.replaceAll(nums, 0, 1);
        19         System.out.println(nums);
        20         //判断-5在集合nums中出现的次数,将输出1
        21         System.out.println(Collections.frequency(nums, -5));
        22         //对nums集合排序
        23         Collections.sort(nums);
        24         System.out.println(nums);
        25         //只有排序后的List集合才可用二分法查询,输出3
        26         System.out.println(Collections.binarySearch(nums, 3));
        27     }
        28 }
        29
        30 /*
        31 [2, -5, 3, 0]
        32 3
        33 -5
        34 [2, -5, 3, 1]
        35 1
        36 [-5, 1, 2, 3]
        37 3
        38 请按任意键继续. . .
        39
        40 */
    • 同步控制:(Java常用集合框架中推荐使用的三么实现类:HashSet、ArrayList和HashMap都是线程不安全的。如果有多条线程访问它们,而且有超过一条的线程试图改变它们,则可能出现错误。Collections提供了多个静态方法用于创建同步集合)
      •  1 import java.util.*;
         2 public class TestSynchronized
         3 {
         4     public static void main(String[] args)
         5     {
         6         //下面程序创建了四个同步集合对象
         7         Collection c = Collections.synchronizedCollection(new ArrayList());
         8         List list = Collections.synchronizedList(new ArrayList());
         9         Set s = Collections.synchronizedSet(new HashSet());
        10         Map m = Collections.synchronizedMap(new HashMap());
        11     }
        12 }
  • 设置不可变集合:
    • emptyXxx()
    • singletonXxx()
    • unmodifiableXxx()
时间: 2024-10-14 14:25:45

Java学习笔记(二)的相关文章

Java学习笔记二:初始化(一)

1.对象初始化 在使用 new 初始化对象时,系统通常使用默认的构造函数,这个构造函数没有返回值,格式为: public class InitializeTest { private int a; // 默认构造函数 public InitializeTest() { } // 自定义构造函数 public InitializeTest(int a) { this.a = a; } } 虽然在使用 new 创建实例时,返回了这个对象的引用,但是这个与没有返回值的void方法不同 //void方法

Java学习笔记二:数据类型

Java学习笔记二:数据类型 1. 整型:没有小数部分,允许为负数,Java整型分4种:int short long byte 1.1 Int最为常用,一个Int类型变量在内存中占用4个字节,取值范围从-2 147 483 6至2 147 483 647 超过20亿,如果用来存储大于20亿的值,最好使用long型. 1.2  int 与Integer: Java中的数据类型分为基本数据类型和复杂数据类型.Int为前者,integer为后者. Integer是int的封装类,提供了很多转换方法,当

Java学习笔记二:初始化(二)

这里主要学习初始化,分为: 1.变量初始化 2.构造函数初始化 3.数组初始化 4.继承初始化   1.变量初始化 成员初始化分为两种: (1)成员变量初始化 在定义成员变量时,如果没有给变量赋于初始值,系统会给出一个默认值. 这里有两种选择:要么使用系统的默认初始值,要么自己定义初始值. 系统给出的默认输出值为: boolean false char [ ] byte 0 short 0 int 0 long 0 float 0.0 double 0.0 refenece null char初

Java学习笔记二(基础语法)

1 Java 是强类型语言,提供的8中基本数据类型有以下几类: Byte :字节类型,一个字节,有符号的8位的整数.字节类型参与运算的时候,会转化为int类型. byte b;b=3;b=(byte)(b*3);  在这里第二个赋值必须经过强制类型转化,否则会编译出错. short:2个字节,Byte可行可以直接赋值给short,但是反过来需要强制类型转化. int:4字节类型的有符号的整数. long:8个字节类型的有符号的整形 char:2个字节的无符号的类型.采用的是Unicode的编码格

数组排序、递归——(Java学习笔记二)

升序: 选择排序: 选定一个元素,一次和后面的元素相比较,如果选定的元素大雨后面的比较元素,就交换位置 先出现最小值,最后出现最大值. public static void main(String[] args) { int[] arr = {5,8,9,12,55,565,421,12,2512,-5,-56}; sortMethod(arr); p(arr); } //排序核心代码 private static void sortMethod(int arr[]) { for(int i =

Java学习笔记二:初始化(三)

3.数组初始化 1.数组是一个固定长度的集合,在初始化大小后就不能改变其长度. 数组分配在堆中,并在栈中存有指向该数组的一个引用. class Arr { public static void main(String[] args) { int[] a = {1, 2, 3, 4}; int[] b = a; for (int i = 0; i < b.length; i++) { b[i]++; } for (int i = 0; i < a.length; i++) { System.ou

Java学习笔记二---环境变量

1.环境变量包括: JAVA_HOME,CLASSPATH,PATH 2.设置环境变量的目的: 路径搜索,方便查找到Java的安装路径.方便搜索用到的类.方便命令执行等. 3.各环境变量的含义: ①.JAVA_HOME,指向jdk的安装目录,通过搜索JAVA_HOME来找到jdk. ②.CLASSPATH,指定类的搜索路径,通过搜索CLASSPATH,看是否能找到使用的类. ③,PATH,指定命令的搜索路径,通过搜索PATH,看是否能找到要执行的命令. 4.各环境变量的值: ①.JAVA_HOM

JAVA学习笔记(二)

简单的做了个登录界面,运用了添加事件响应,但添加单选框时没有显示出来. package 界面设计; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class JTextFieldDemo extends JFrame implements ActionListener{ JTextField jtf=new JTextField(10); JPasswordField jpf=new JPassw

黑马程序员——JAVA学习笔记二(语法基础)

1,     Java程序都是以类的形式存在的,所以需要告诉虚拟机需要加载类的位置,那么可以设置classpath变量.classpath变量如果有;,则表示还会在当前目录查找,没有;则不会在当前目录查找. 当然如果没有classpath也会在当前目录查找. 2,    rd删除目录,加/S可以删整个目录,Windows从里向外删除. 3,    一个文件只有一个public类,文件名必须和类名相同,如果不是友好类,则不需要同名. 4,    JAVA一共有50个关键字 关键字是电脑语言里事先定

Java学习笔记二——标识符和关键字

标识符 定义 标识符的定义:对各种变量.方法和类等要素命名时使用的字符序列成为标识符. 简单地说,就是凡是自己可以起名字的地方都叫标识符,都要遵守标识符的规则. 命名规则 标识符只能由字母.下划线"_".美元符号"$"或数字组成 标识符只能以字母.下划线或美元符开头 标识符不能是Java关键字和保留字 标识符大小写敏感,长度无限制 约定俗成 为了能使Java代码更好地维护和美观,通常写Java代码是都会遵循一些约定俗成的规矩,如下: 标识符要起的见名知意,可以由多个