1.泛型类的使用
1)看到<>就是泛型
2)
3)泛型背后的机制是作用在编译器间的
4)运行期间没有泛型的概念,统统认为是Object类型的引用(有一定的歧义)
2.包装类
int–》Interger
char–》Character
1)装箱(boxing)和拆箱(unboxing)
2)java提供自动装箱和拆箱
3)
关于List:支持实例化的只有两个类 ArrayList、LinkedList
3.应用–扑克牌
1)买一副牌(buyDeck):按花色A-K
2)洗牌(shuffle)
3)玩游戏–三个人、每人总共5张牌、按顺序发牌(send)
4)♠2在谁手中谁就输了(play)
注意:
1)在paly方法中,不能直接card==hands.get(i).get(j) //是否指向同一张牌
2)java中进行对象值语义相等判断,不能直接比较引用是否相等,应覆写Object.equals方法
3)Node p; Node q; p == q; //是错误的
4)在equals方法中,不能直接this.value == obj.value; //因为obj不能.val,需要向下转型才可以取val
5)清楚泛型定义及使用
public class Card {
public int value;
public String color;
public Card(int value, String color) {
this.value = value;
this.color = color;
}
@Override
public String toString() { //覆写toString方法
String v;
if (value == 1) { //1--A 美观
v = "A";
} else {
v = String.valueOf(value);
}
return String.format("[%s %s]", color, v);
}
@Override
public boolean equals(Object obj) {//覆写equals方法
// this 是 o 是否语义相等
if (obj == null) {
return false;
}
if (!(obj instanceof Card)) {//判断obj是不是Card类的对象
return false;
}
if (obj == this) {
return true;
}
// this.value == obj.value;
// 需要向下转型
Card o = (Card)obj;
return value == o.value && color.equals(o.color); //不能直接color == o.color
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CardGame {
private static final String[] COLORS = {
"♠", "♥", "♦", "♣"
};
private static List<Card> buyDeck() {
List<Card> deck = new ArrayList<>(52); //52是容量
//如果此时deck.get(0); 下标错误
for (int i = 0; i < 4; i++) {
String color = COLORS[i];
for (int j = 1; j <= 13; j++) {
int value = j;
Card card = new Card(value, color);
deck.add(card);
}
}
return deck;
}
private static void shuffle(List<Card> deck) {
Random random = new Random(20190916); //随机种子相同 生成随机数相同
for (int i = deck.size() - 1; i > 0; i--) {
int r = random.nextInt(i); //[0,i) 生成0-i随机数
swap(deck, i, r);
}
}
private static void swap(List<Card> deck, int i, int j) {
Card t = deck.get(i);
deck.set(i, deck.get(j));
deck.set(j, t);
}
public static void main(String[] args) {
List<Card> deck = buyDeck();
System.out.println("=============布牌=============");
System.out.println(deck);
shuffle(deck);
System.out.println("=============洗牌=============");
System.out.println(deck);
List<List<Card>> hands = new ArrayList<>(); //玩家手里的牌
send(hands, deck, 3, 5); //发牌
System.out.println("========玩家1手里的牌=========");
System.out.println(hands.get(0));
System.out.println("========玩家2手里的牌=========");
System.out.println(hands.get(1));
System.out.println("========玩家3手里的牌=========");
System.out.println(hands.get(2));
System.out.println("==========剩余的牌============");
System.out.println(deck);
play(hands);
}
private static void play(List<List<Card>> hands) {
Card card = new Card(2, "♠"); //先定义一张♠2的card
for (int i = 0; i < hands.size(); i++) { //一个人一个人的判断
if (hands.get(i).contains(card)) { // boolean contains(Object o) ---判断o是否在线性表中
System.out.println("=========♠2在谁手里?=========");
int player = i+1;
System.out.println( "玩家"+player +" 输了");
return;
}
}
/*
for (int j = 0; j < hands.get(i).size(); j++) {
// 错误的
Card handCard = hands.get(i).get(j);
if (card.equals(handCard)) {
System.out.println("%d 输了");
return;
}
}
*/
}
//发牌
private static void send(List<List<Card>> hands, List<Card> deck, int numPerson, int numCard) {
// 调用 get 之前一定要保证元素是存在的
for (int k = 0; k < numPerson; k++) {
hands.add(new ArrayList<>()); //首先把引用插入hands中
}
for (int i = 0; i < numCard; i++) {
for (int j = 0; j < numPerson; j++) {
// 抓牌
Card card = deck.remove(0); //删除玩家取走的牌--头删 (每次都发第0张牌)
hands.get(j).add(card);
}
}
}
}
4.覆写equals方法
凡是需要用到引用的相等语义比较,必须调用equals方法
凡是自定义类,会被调用equals方法,就必须覆写
eg:List.contains//内部会调用元素类型的equals
1)如果是null,返回false
2)如果不是一个类型,返回false
3)根据类的定义来比较
注意:
1)如果不覆写,Object.equals默认的行为是:this == o;
2)p == q //判断p和q是否指向同一对象
p.equals(q) //判断p指向的对象和q指向的对象是否(语义)相等
3)eg:p != q但p和q语义相等
5.覆写equals实例
1)eg1:
public class Article {
String title;
String author;
String content;
String publishedAt;
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Article)) {
return false;
}
if (obj == this) {
return true;
}
Article a = (Article)obj;
if (!title.equals(a.title)) {
return false;
}
if (!author.equals(a.author)) {
return false;
}
if (!content.equals(a.content)) {
return false;
}
return publishedAt.equals(a.publishedAt);
}
}
2)eg2:
public class Student {
public String sn;
public String name;
public int age;
public int gender;
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Student)) {
return false;
}
if (this == obj) {
return true;
}
return sn.equals(((Student) obj).sn); //学号可代表一个人
}
}
6.杨辉三角
方法1:
1)创建一个 List<List> list = new ArrayList<>(); //存放最终杨辉三角数据
2)放入nums(eg:nums=5)个List // [ [],[],[],[],[] ]
3)全部填入1
4)修改需要修改的数值
需要修改行的所属下标:[2,numRows)
需要修改列的所属下标:[1,i)
方法2:
1)List<List> list
2)循环numRows次,每次new ArrayList<>() innerList;然后插入 list.add(innerList);
第一行:innerList.add(1); 第二行:innerList.add(1); innerList.add(1);
第三行:innerList.add(1); ……中间计算…… innerList.add(1);、
第n行:……
方法3:直接全部插入
import java.util.ArrayList;
import java.util.List;
public class PascalsTriangle {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<>(); //存放最终杨辉三角数据
for (int i = 0; i < numRows; i++) {
list.add(new ArrayList<>()); // [ [],[],[],[],[] ]
}
for (int i = 0; i < numRows; i++) {
for (int j = 0; j <= i; j++) {
list.get(i).add(1); //全部填入1
}
}
for (int i = 2; i < numRows; i++) { //修改杨辉三角中不是1的地方
for (int j = 1; j < i; j++) {
int a = list.get(i - 1).get(j - 1);
int b = list.get(i - 1).get(j);
list.get(i).set(j, a + b);
}
}
return list;
}
public List<List<Integer>> generate2(int numRows) {
List<List<Integer>> list = new ArrayList<>();
list.add(new ArrayList<>());
// 第一行
list.get(0).add(1);
// 第二行
list.add(new ArrayList<>());
list.get(1).add(1);
list.get(1).add(1);
for (int i = 2; i < numRows; i++) {
list.add(new ArrayList<>());
list.get(i).add(1);
//中间计算
for (int j = 1; j < i; j++) {
int a = list.get(i - 1).get(j - 1);
int b = list.get(i - 1).get(j);
list.get(i).add(a + b); // 这里不能调用 set(下标问题)
}
list.get(i).add(1);
}
return list;
}
public List<List<Integer>> generate3(int numRows) {
/*
int[][] result = {
{1},
{1,1},
{1,2,1},
{1,3,3,1},
{1,4,6,4,1},
{1,5,10,10,5,1}
};
*/
List<List<Integer>> list = new ArrayList<>();
list.add(new ArrayList<>());
// 第一行
list.get(0).add(1);
// 第二行
list.add(new ArrayList<>());
list.get(1).add(1);
list.get(1).add(1);
// 第三行
list.add(new ArrayList<>());
list.get(2).add(1);
list.get(2).add(2);
list.get(2).add(1);
// 第四行
list.add(new ArrayList<>());
list.get(3).add(1);
list.get(3).add(3);
list.get(3).add(3);
list.get(3).add(1);
// 第五行
list.add(new ArrayList<>());
list.get(4).add(1);
list.get(4).add(4);
list.get(4).add(6);
list.get(4).add(4);
list.get(4).add(1);
if (numRows == 5) {
return list;
}
if (numRows < 5) {
list.subList(0, numRows);
}
// 剩余部分用上述办法继续计算
return null;
}
public static void main(String[] args) {
System.out.println("================方法1=================");
System.out.println(new PascalsTriangle().generate(5));
System.out.println("================方法2=================");
System.out.println(new PascalsTriangle().generate2(5));
System.out.println("================方法3=================");
System.out.println(new PascalsTriangle().generate3(5));
}
}