private List<Reducer> estimateReducers(List<Mapper> newMapperList, boolean useRuntimeMaxJvmHeap) {
		int fReducerNum = finishedConf.getMapred_reduce_tasks();

		if(fReducerNum == 0)
			return null;
		//if(isMapperConfChanged == false && isSplitSizeChanged == false && isReducerConfChanged == false) 
		//	return job.getReducerList();
		
		ReducerEstimator reducerEstimator = new ReducerEstimator(finishedConf, newConf, newMapperList, useRuntimeMaxJvmHeap);
		
		List<Reducer> newReducerList = new ArrayList<Reducer>();
		
		//reducer number doesn't change
		//reducerIndex means which partition of mappers' output will be received by the new reducer 
		if(fReducerNum == newConf.getMapred_reduce_tasks()) {
			for(int i = 0; i < fReducerNum; i++) {
				//use the corresponding finished reducer to estimate the new reducer
				Reducer newReducer = reducerEstimator.estimateNewReducer(job.getReducerList().get(i), i);
				newReducerList.add(newReducer);
			}
		}
		//reducer number changes
		else {
			for(int i = 0; i < newConf.getMapred_reduce_tasks(); i++) {
				//use all the finished reducers' infos to estimate the new reducer
				Reducer newReducer = reducerEstimator.estimateNewReducer(job.getReducerList(), i);
				newReducerList.add(newReducer);
			}
		}
		return newReducerList;
	}