【ThinkingInJava】32、递归计数

/**
* 书本:《Thinking In Java》
* 功能:为了对pet进行计数,我们做一个能跟踪各种不同类型的Pet的数量的工具,用map。这里使用动态instanceof()
* 		我们可以使用Class.isAssignableFrom(),创建一个不局限于Pet的计数通用工具
* 文件:PetCount3.java
* 时间:2015年4月14日09:56:41
* 作者:cutter_point
*/
package net.mindview.util;

import java.util.HashMap;
import java.util.Map;

import Lesson14TypeInformation.pets.Pet;

public class TypeCounter extends HashMap<Class<?>, Integer>
{
	private Class<?> baseType;

	public TypeCounter(Class<?> baseType)
	{
		this.baseType = baseType;
	}

	public void count(Object obj)
	{
		Class<?> type = obj.getClass();
		if(!baseType.isAssignableFrom(type))//判断是不是这个类型
		{
			throw new RuntimeException(obj + " incorrect type: " + type + ", should be type or subtype of" + baseType);
		}
		this.countClass(type);		//添加一个类型
	}

	private void countClass(Class<?> type)
	{
		Integer quantity = this.get(type);	//获取这个类型属性的个数
		//添加一个,或新增一个类对象
		this.put(type, quantity == null? 1 : quantity + 1);
		//得到父类,引用
		Class<?> superClass = type.getSuperclass();
		if(superClass != null && baseType.isAssignableFrom(superClass))
			countClass(superClass);	//递归,父类型也会加1
	}

	public String toString()
	{
		StringBuilder result = new StringBuilder("{ ");
		for(Map.Entry<Class<?>, Integer> pair : this.entrySet())//遍历所有的不重复的对象
		{
			result.append(pair.getKey().getSimpleName());	//类名
			result.append(" = ");
			result.append(pair.getValue());
			result.append(", ");
		}

		result.delete(result.length() - 2, result.length());	//去掉最后的", "
		result.append(" }");
		return result.toString();
	}

}

这个就是当一个类进来的时候我们要计数,但是这个类计数了他的父类呢?父类也应该加1的,那么父类的父类呢?所以我们用递归,一层一层的向上递归,直到找到基类,然后把基类也+1.

/**
* 书本:《Thinking In Java》
* 功能:为了对pet进行计数,我们做一个能跟踪各种不同类型的Pet的数量的工具,用map。这里使用动态instanceof()
* 文件:PetCount4.java
* 时间:2015年4月14日09:25:29
* 作者:cutter_point
*/
package Lesson14TypeInformation;

import net.mindview.util.TypeCounter;
import static net.mindview.util.Print.*;

import Lesson14TypeInformation.pets.Pet;
import Lesson14TypeInformation.pets.Pets;

public class PetCount4
{
	public static void main(String args[])
	{
		TypeCounter counter = new TypeCounter(Pet.class);
		for(Pet pet : Pets.createArray(20))
		{
			printnb(pet.getClass().getSimpleName() + " ");
			counter.count(pet);
		}
		print();
		print(counter);
	}
}

输出:

Rat -obj2 Manx -obj2 Cymric -obj2 Mutt -obj2 Pug -obj2 Cymric -obj2 Pug -obj2 Manx -obj2 Cymric -obj2 Rat -obj2 EgyptianMau -obj2 Hamster -obj2 EgyptianMau -obj2 Mutt -obj2 Mutt -obj2 Cymric -obj2 Mouse -obj2 Pug -obj2 Mouse -obj2 Cymric -obj2

{ Dog = 6, Rodent = 5, Rat = 2, Hamster = 1, Pug = 3, Cymric = 5, Manx = 7, Cat = 9, Mutt = 3, Pet = 20, Mouse = 2, EgyptianMau = 2 }  obj1

时间: 2024-12-28 10:17:11

【ThinkingInJava】32、递归计数的相关文章

UVa 12627 (递归 计数 找规律) Erratic Expansion

直接说几个比较明显的规律吧. k个小时以后,红气球的个数为3k. 单独观察一行: 令f(r, k)为k个小时后第r行红气球的个数. 如果r为奇数,f(r, k) = f((r+1)/2, k-1) * 2 如果r为偶数,f(r, k) = f(r/2, k-1) 令g(r, k)为k个小时后前r行红气球的个数. 如果r为偶数,g(r, k) = g(r/2, k-1) * 3; 如果r为奇数,g(r, k) = g(r-1, k) + f(r, k); 因此f和g都可以用递归求解. 1 #inc

python 内置&&递归

lambda 优点: 1:可以简单使用一个脚本来替代我们的函数 2:不用考虑命名的问题 3:简化代码的可读性,不用跳转到def了,省去这样的步骤 内置函数:bif filter:过滤器 map:映射  1 >>> lambda x: 2*x+1 2 <function <lambda> at 0x00000000026C6AC8> 3 >>> g=lambda x: 2*x+1 4 >>> g(3) 5 7 6 >>

关于快排的递归实现

*/--> 关于快排的递归实现 Table of Contents 1 引子 2 源码 1 引子 自己以前写过一篇关于快速排序的blog,但是没采用递归,而且当时的blog是完全手写的.但是现在都用Emacs工作,所以就分开了. 虽然以前写过快排,但是过了一段时间再来写,虽然有递归的引子,但还是对递归的初始入口不会,始终不得其解,还是在参看了以前的代码才写了出来. 2 源码 快速排序的递归实现: 1: #include <stdio.h> 2: #include <stdlib.h

30.2 自旋、线程所有权和递归

/// <summary> /// 其他混合锁 /// </summary> internal sealed class AnotherHybridLock : IDisposable { //由基元用户模式构造(Interlocked的方法)使用 private int _waiters = 0; //AutoResetEvent 是基元内核模式构造 private AutoResetEvent _waiterLock = new AutoResetEvent(false); /

[.net]基元线程同步构造

1 /* 基元线程同步构造 2 用户模式构造: 3 易变构造(Volatile Construct) 4 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimistic Concurrency Control,乐观并发控制) 5 内核模式构造: 6 事件构造(Event) 7 信号量构造(Semaphore) 8 互斥体构造(Mutex) 9 */ 10 11 //易变构造,Volatile.Write()之前的所有字段写入操作,必须再该方法调用

C++多线程那些事

线程之间的关系一般有两种,一种是互斥,一种是同步,互斥可以表现为两个线程同时争夺同一个资源,同步可以表现为两个线程按一定次序完成一个任务(如A 完成任务的前半部分,紧接着需要线程B 完成线程的后半部分) 在C++中处理上面两种关系的常用方法是: 关键段.事件.互斥量.信号量. 注意C++开启新的线程一定使用_beginthreadex函数而不要使用CreateThread函数,因为后者对系统中的全局变量没有保护,所以多个线程程环境下,容易出现系统的全局变量的值被覆盖的情况,而前者每个线程都有单独

PHP数组函数总结

一.新建数组 数组没有大小限制,所以只需建立引用就可以创建数组,例如: $state[0]= '111'; $state[1]= '222'; 如果索引值是数值索引而且是递增的,还可以在创建时省略索引值. $state[] ='111'; $state[] ='222'; 可以使用array()创建数组,如: $state =array('111', '222'); $state =array('one'=>'111', 'two'=>'222'); 使用list()提取数组,例如: $sta

线程与内核对象的同步-2

等待定时器内核事件CreateWaitableTimer(PSECURITY_ATTRIBUTES psa,BOOL fManualReset,PCTSTR pszName);进程可以获得它自己的与进程相关的现有等待定时器的句柄.HANDLE OpenWaitableTimer(DWORD dwDesiredAccess,BOOL bInheritHandle,PCTSTR pszName); 等待定时器对象总是在未通知状态中创建,必须调用SetWaitableTimer函数来告诉定时器你想在何

C#多线程之线程同步3

在上一篇C#多线程之线程同步2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier构造.ReaderWriterLockSlim构造和SpinWait构造. 七.使用Barrier构造 在这一小节中,我们将学习一个比较有意思的同步构造:Barrier.Barrier构造可以帮助我们控制多个等待线程达到指定数量后,才发送通知信号,然后所有等待线程才能继续执行,并且在每次等待线程达到指