黑马程序员-重要代码记录Part2(持续跟新)


-----------  android培训 java培训 、java学习型技术博客、期待与您交流! ------------

黑马程序员-重要代码记录
(原打算一个帖子收集,发现多了就不方便回顾,特另开)

1.关于猫狗鱼问题的思路

我的代码:
import java.util.ArrayList;
import java.util.Random;

public class Cross_new {
	public static void main(String[] args) {
		//开始过河.
		doTransport();
	}

	public static void doTransport() {
		// 抽象出猫,鱼,狗和两岸.
		ArrayList<String> arr1 = new ArrayList<String>();
		ArrayList<String> arr2 = new ArrayList<String>();
		arr1.add("鱼");
		arr1.add("猫");
		arr1.add("狗");
		// 农夫将要携带到船上动物.(前一字符表示农夫当前携带动物,后一字符表示上次农夫携带的动物,为了让农夫不出现重复拿同一个动物的情况)
		System.out.println("农夫,猫,鱼,狗都在此岸,开始过河.\n");
		String boat = new String("--");
		while (arr1.size() > 0) {
			move(arr1, arr2, boat);
		}
		System.out.println("\n农夫,猫,鱼,狗都到达彼岸.");
	}

	public static void move(ArrayList<String> arr1, ArrayList<String> arr2,String boat) {
		//农夫船上是否有动物,有则不需随机选择携带.
		if (boat.startsWith("-")) {
		int one=0;
		do{
				// 农夫从此岸随机带上一个动物.
				one = new Random().nextInt(arr1.size());
			}while(arr1.get(one)==boat.substring(1, 2));
			boat = arr1.get(one)+boat.substring(1,2);
			arr1.remove(one);
		}
		// 判断此岸是否和谐
		if (ifNice(arr1)) {
			// 此岸和谐,农夫则将动物送去彼岸.
			arr2.add(boat.substring(0, 1));
			System.out.println("--->农夫带" + boat.substring(0, 1) + "去彼岸    ");
			//首先判断是否将三个动物都放彼岸,是则无需判断是否和谐.
			if(arr2.size()==3){
				return;
			}
			// 判断彼岸是否和谐.
			if (ifNice(arr2)) {
				// 彼岸和谐,农夫则完成此次运送.
				boat="-"+boat.substring(0, 1);
				System.out.println("    农夫单独回此岸<---");
			} else {
				// 彼岸不和谐,农夫则将岸上动物与携带动物交换.送回此岸.
				boat=arr2.get(0)+boat.substring(0, 1);
				System.out.println("    农夫带" +boat.substring(0, 1)+ "回此岸<---");
				arr2.remove(0);
				arr1.add(boat.substring(0, 1));
				boat="-"+boat.substring(0, 1);
			}
		} else {
			// 如果此岸不和谐则放回此岸.
			arr1.add(boat.substring(0, 1));
			boat="-"+boat.substring(0,1);
		}
	}

	public static boolean ifNice(ArrayList<String> arr) {// 判断是能否共存.
		if ((arr.contains("猫") && arr.contains("狗"))
				|| (arr.contains("鱼") && arr.contains("猫"))) {
			return false;
		} else {
			return true;
		}
	}
}
	
朋友的代码:
public class Test10_1 {

	public static void main(String[] args) {
		// 首先创建三个对象
		Animal cat = new Cat("cat");
		Animal dog = new Dog("dog");
		Animal fish = new Fish("fish");
		// 定义两个链表存放对象
		LinkedList<Animal> beforeCrossing = new LinkedList<Animal>();
		LinkedList<Animal> afterCrossing = new LinkedList<Animal>();
		
		beforeCrossing.add(cat);
		beforeCrossing.add(dog);
		beforeCrossing.add(fish);

		while (beforeCrossing.size() != 0) {
			// 从beforeCrossing取出一个Animal
			Animal ani = beforeCrossing.removeFirst();
			// 如果剩下两个Animal,看看剩下的Animal能否和平共处
			if (beforeCrossing.size() == 2) {
				if (beforeCrossing.getFirst().friendlyWith(beforeCrossing.getLast())) {
					// 如果能合同共处,把取出的动物送到afterCrossing
					afterCrossing.addLast(ani);
					System.out.println(ani.getName() + "被送到对岸");
				} else {
					// 如果剩下的动物不能和平共处,则把取出的Animal再次插入beforeCrossing
					beforeCrossing.addLast(ani);
				}
			} else {
				// 否则先把动物送到对岸
				afterCrossing.addLast(ani);
				System.out.println(ani.getName() + "被送到对岸");
				// 再判断对岸的Animal能否和平共处
				if (afterCrossing.size() == 2) {
					// 如果不能和平共处,则把对岸的原先的动物给送回来
					if (!afterCrossing.getFirst().friendlyWith(afterCrossing.getLast())) {
						ani = afterCrossing.removeFirst();
						beforeCrossing.addLast(ani);
						System.out.println(ani.getName() + "被送了回来");
					}
				}
			}

		}

	}
}

abstract class Animal {
	private String name;

	public Animal() {
		super();
	}

	public Animal(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract boolean friendlyWith(Animal ani);
}

class Cat extends Animal {

	public Cat() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Cat(String string) {
		super(string);
	}

	@Override
	public boolean friendlyWith(Animal ani) {
		if (ani.getClass().getSimpleName().equals("Dog")
				|| ani.getClass().getSimpleName().equals("Fish"))
			return false;
		else
			return true;
	}

}

class Dog extends Animal {

	public Dog() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Dog(String string) {
		super(string);
	}

	@Override
	public boolean friendlyWith(Animal ani) {
		if (ani.getClass().getSimpleName().equals("Cat"))
			return false;
		else
			return true;
	}

}

class Fish extends Animal {

	public Fish() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Fish(String string) {
		super(string);
	}

	@Override
	public boolean friendlyWith(Animal ani) {
		if (ani.getClass().getSimpleName().equals("Cat"))
			return false;
		else
			return true;
	}

}

总结:
这道题是从黑马基础题上看到的,刚开始以为没什么知识点,纯if判断就ok.后来才发现,可以很有知识点,
1.我再上面放出的第一个代码是我的思路.第二个是以朋友的思路.
我的代码在一开始,就没有我朋友的那种相当浓烈的面向对象思想.他将猫狗鱼都封装成了类,继承动物类,有方法Friendly.对于Java的面向对象思想来说,貌似很切合.
我的代码思路就是抽象了两岸,小船,用集合和String[]抽象了他们,并将动物抽象为了字符数组中的字符.虽然,我自认为自己的方法看起来更简单,但是不得不承认,思想上,败给了朋友的代码.
所以,我觉得Java前期的学习,必须注重思维的培养,培养面向对象的思想,深化封装,继承,多态的思维模式.
有了思想,语言基础都是可以用时间补上的....

----------------------------------------------------------

2.按字节为截取字符代码引发的思考

我的代码:
/*
 * 需求:
 * 编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
 * 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文.
 * 
 * 思路:
 * 字符串的字节文件表示中,英文字母为一个byte型数据表示,而汉子为两个byte数据表示.
 * 对给定的一个字符串,用toCharArray()和getByte()方法分别转换为字符,字节数组.
 * 如果是字母,则对应数组中元素的数值应该是相等的,否则不等,且为字节数组中两个元素对应字符数组中一个元素.
 * 
 * 步骤:
 * 1.键盘录入一个字符串对象.
 * 2.转换并接受用String类中方法得到的字符数组与字节数组.
 * 3.键盘接收需要截取字符串的字节数.
 * 4.以字节数组元素来判定截取字节数,以与字符串数组元素的对比判断是否该将对应字符截取.
 * 5.打印出截取后字符串.
 * */

public class Test10 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.println("请输入需要截取的字符串:");
		String str = in.nextLine();
		subPartOfString(str);
	}
	
	//定义方法,按需求截取字符串中对应字节字符串.
	public static void subPartOfString(String str) {
		Scanner in = new Scanner(System.in);
		char[] charArr = str.toCharArray();
		byte[] byteArr = str.getBytes();
		int n = 0;
		while (true) {
			System.out.println("请输入需要截取字节数:(数字)");
			n = in.nextInt();
			if (n > byteArr.length || n <= 0) {
				System.out.println("输入的截取字节数有误,请重新输入.");
				continue;
			} else {
				break;
			}
		}
		int j = 0, i = 0, count = 1;//i用于控制截取字节数,即循环增量;j为截取后字符数.
		while (i < n) {
			if (charArr[j] - byteArr[i] == 0) {//如果当前字节位为字母,则加入截取后字符串.
				i++;
				j++;
			} else {//如果当前字节为汉子,则占两个字节,当且仅当截取了两个字节才将该字符加入截取后字符串.
				count++;
				i++;
				j += count % 2;
			}
		}
		System.out.println("截取后新字符串为:\n"+new String(charArr, 0, j));
	}
}
张孝祥老师的方法代码:
    public static void main(String[] args) throws Exception{

            String str = "我a爱中华abc我爱传智def';

            String str = "我ABC汉";

            int num = trimGBK(str.getBytes("GBK"),5);

            System.out.println(str.substring(0,num) );

      }

      

      public static int  trimGBK(byte[] buf,int n){

            int num = 0;

            boolean bChineseFirstHalf = false;

            for(int i=0;i<n;i++)

            {

                  if(buf[i]<0 && !bChineseFirstHalf){

                        bChineseFirstHalf = true;

                  }else{

                        num++;

                        bChineseFirstHalf = false;                      

                  }

            }

            return num;

      }

 

总结:
在这里,先对已逝的张孝祥老师报以有种的感谢...您一路走好.
这道题,也是从黑马入学基础题目中侬到的题目.在自己解决的时候,对如何判断是否截取这个占用了两个字节的一个汉子字符相当繁琐,多定义了两个集合,多用了几个循环增量.在看张孝祥老师的就业面试宝典时,突然发现,这道题老师的代码,很好.
我是这么顺着老师的代码走的思路:
1.方法定义中的参数列表为:一个由目标字符串转换成的字节数组,截取的字节数.
2.方法中,在循环截取的代码外,定义了截取长度的初始值0 ,一个判断是否为中文字符的布尔变量.for循环的判断中,用字节数据是否为负数 (汉子由两个负的字节数据组成)和是否截取过1个字符的前一个字节.
3. 在循环体结束(两处,if和else)中分别对该辅助判断的布尔变量进行新的赋值 .
4.返回该结果.
事实上,我自己的代码中思路何老师差不多,但是没能思路明了的用一个布尔型变量来接收.实际上就是封装了我代码中的循环增量判断和赋值.其实想想也是,当循环增量是以模2为判断辅助条件,用false,或true,完全可以既简便由明了的替代这个循环增量.
总之,学习老师等高手的思想,思路,路还很长...

----------------------------------------------------------------------





----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

详情请查看:http://edu.csdn.net/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值