Binary tree variable type issue - java

I'm having trouble with a method I wrote to insert string words into a binary tree. The below code is the method in question. Basically, the word is inserted if it is not yet in the tree (as a BinaryTreeNode), and if it is in the tree, its frequency (count variable within BinaryTreeNode) is increased by one. My problem is with the temporary variable searchWord. Defining it as a String creates a type mismatch and a statement that says getFrequency() is not defined for type String. The generic type T is only there as a placeholder - it too does not work. What should it therefore be defined as?
buildBinaryTree method:
public static void buildBinaryTree(String word) {
//if word is already in tree
if(wordTree.contains(word)) {
//find existing word node
T searchWord = wordTree.find(word); //problem here
//increment frequency by 1
searchWord.setFrequency(searchWord.getFrequency() + 1);
} else {
//add word to tree
System.out.println(word);
wordTree.addElement(word);
}
}
BinaryTreeNode constructor:
/**
* Creates a new tree node with the specified data.
* #param obj the element that will become a part of the new tree node
*/
BinaryTreeNode(T obj) {
element = obj;
left = null;
right = null;
frequency = 1;
}
Frequency get/set methods:
/**
* Gets the frequency.
* #return the frequency
*/
public int getFrequency() {
return frequency;
}
/**
* Sets the frequency.
* #param frequency the frequency to set
*/
public void setFrequency(int frequency) {
this.frequency = frequency;
}

After talking in chat, you should define a class that has both a String and int that you use as the type to place in the binary tree, to replace the type variable T. Then, you can define methods such as getString() to return the String, incrementFrequency() to add one to the frequency, etc. When you get an object out of the binary tree, it will be the right type to call these methods.

Related

adding and deleting from ordered Arraylist

I need to add an Object to an ordered ArrayList depending on an attribute inside of the Object. I know how to use the .add method to add the object but I don't know how to search for the right place for it using the compareTo() method. And also I need to remove an Object from the ArrayList if the Object contains a certain String but I cant figure out how to access the Object attributes from the ArrayList.
Realtor Object
/**
* Constructor for Realtor object using parameter
* #param readData - array of data from line
*/
public Realtor(String[]readData){
licenseNumber = readData[2];
firstName = readData[3];
lastName = readData[4];
phoneNumber = readData[5];
commission = Double.parseDouble(readData[6]);
}
RealtorLogImpl
public class RealtorLogImpl {
private ArrayList<Realtor> realtorList;
/**
* Add Realtor object to ordered list
* #param obj - Realtor object
*/
public void add(Realtor obj){
//needs to be added into correct place depending on Realtor licenseNumber
realtorList.add(obj);
}
/**
* Delete Realtor object from list if license matches
* and return true if successful
* #param license
* #return
*/
public boolean remove (String license){
//need to remove Realtor with specific licenseNumber and return true if successful
}
I'm assuming you are using java 8. Some of these things have not been implemented in java 7 so keep that in mind.
First, to remove the items I would recommend using the removeif() method on the arraylist. This takes a lambda expression which could be something like x -> x.getString().equals("someString").
Second, You could add the object to the array then simply sort the array afterwards. You would just have to write a comparator to sort it by.
Here is some basic code; I have no compiler here, so you might find small errors/typos.
I'm sure there are better classes you can use instead of managing your own ordered list.
To insert:
public bool add(Realtor obj) {
int idx = 0;
for (Realtor s : realtorList) {
if (s.licenseNumber.equals(item.licenseNumber)) {
return false; // Already there
}
if (s.licenseNumber.compareTo(item.licenseNumber) > 0) {
orderedList.add(idx, item);
return true; // Inserted
}
idx++;
}
orderedList.add(item);
return true; // Appended
}
To delete:
public bool deleteItem(String license) {
int idx = 0;
for (Realtor s : realtorList) {
if (s.licenseNumber.equals(license)) {
realtorList.remove(idx);
return true; // Removed
}
}
return false; // Not found
}
To answer your question check the following snippet (requires Java 8) and adapt on your demand:
public static void main(String[] args) {
final List<String> list = new ArrayList<>();
list.add("Element 1");
list.add("Element 2");
list.add("Element 3");
/*
* Insert at a specific position (add "Element 2.5" between "Element 2" and "Element 3")
*/
Optional<String> elementToInsertAfter = list.stream().filter(element -> element.equals("Element 2")).findFirst();
if(elementToInsertAfter.isPresent()) {
list.set(list.indexOf(elementToInsertAfter.get()) + 1, "Element 2.5");
}
/*
* Remove a particular element (in this case where name equals "Element 2")
*/
list.removeIf(element -> element.equals("Element 2"));
}
#add(element) just adds an element to the list. In case of an ArrayList it's added at the end. If you want to insert an element at a particular position you need to use #set(index,element)
But instead of inserting your element at a particular position manually you should maybe use a comparator instead. See java.util.List.sort(Comparator<? super E> e)

How do I get the most frequent word in a Map and it's corresponding frequency of occurrence using Java 8 streams?

I have a class IndexEntry which looks like this:
public class IndexEntry implements Comparable<IndexEntry>
{
private String word;
private int frequency;
private int documentId;
...
//Simple getters for all properties
public int getFrequency()
{
return frequency;
}
...
}
I am storing objects of this class in a Guava SortedSetMultimap (which allows for multiple values per key) where I am mapping a String word to some IndexEntrys. Behind the scenes, it maps each word to a SortedSet<IndexEntry>.
I am trying to implement a sort of indexed structure of words to documents and their occurrence frequencies inside the documents.
I know how to get the count of the most common word, but I can't seem to get the word itself.
Here is what I have to get the count of the most common term, where entries is the SortedSetMultimap, along with helper methods:
public int mostFrequentWordFrequency()
{
return entries
.keySet()
.stream()
.map(this::totalFrequencyOfWord)
.max(Comparator.naturalOrder()).orElse(0);
}
public int totalFrequencyOfWord(String word)
{
return getEntriesOfWord(word)
.stream()
.mapToInt(IndexEntry::getFrequency)
.sum();
}
public SortedSet<IndexEntry> getEntriesOfWord(String word)
{
return entries.get(word);
}
I am trying to learn Java 8 features because they seem really useful. However, I can't seem to get the stream working the way I want. I want to be able to have both the word and it's frequency at the end of the stream, but barring that, if I have the word, I can very easily get the total occurrences of that word.
Currently, I keep ending up with a Stream<SortedSet<IndexEntry>>, which I can't do anything with. I don't know how to get the most frequent word without the frequencies, but if I have the frequency, I can't seem to keep track of the corresponding word. I tried creating a WordFrequencyPair POJO class to store both, but then I just had a Stream<SortedSet<WordFrequencyPair>>, and I couldn't figure out how to map that into something useful.
What am I missing?
I think it would be a better design to use the documentId as the key of the TreeMultimap rather than the word:
import com.google.common.collect.*;
public class Main {
TreeMultimap<Integer, IndexEntry> entries = TreeMultimap.<Integer, IndexEntry>create(Ordering.arbitrary(), Ordering.natural().reverse());
public static void main(String[] args) {
// Add elements to `entries`
// Get the most frequent word in document #1
String mostFrequentWord = entries.get(1).first().getWord();
}
}
class IndexEntry implements Comparable<IndexEntry> {
private String word;
private int frequency;
private int documentId;
public String getWord() {
return word;
}
public int getFrequency() {
return frequency;
}
public int getDocumentId() {
return documentId;
}
#Override
public int compareTo(IndexEntry i) {
return Integer.compare(frequency, i.frequency);
}
}
You can then implement the methods that you had before with the following:
public static int totalFrequencyOfWord(String word) {
return entries.values()
.stream()
.filter(i -> word.equals(i.getWord()))
.mapToInt(IndexEntry::getFrequency)
.sum();
}
/**
* This method iterates through the values of the {#link TreeMultimap},
* searching for {#link IndexEntry} objects which have their {#code word}
* field equal to the parameter, word.
*
* #param word
* The word to search for in every document.
* #return
* A {#link List<Pair<Integer, Integer>>} where each {#link Pair<>}
* will hold the document's ID as its first element and the frequency
* of the word in the document as its second element.
*
* Note that the {#link Pair} object is defined in javafx.util.Pair
*/
public static List<Pair<Integer, Integer>> totalWordUses(String word) {
return entries.values()
.stream()
.filter(i -> word.equals(i.getWord()))
.map(i -> new Pair<>(i.getDocumentId(), i.getFrequency()))
.collect(Collectors.toList());
}
Native solution by JDK:
entries.keySet().stream()
.collect(groupingBy(IndexEntry::getWord, summingInt(IndexEntry::getFrequency)))
.values().stream().max(Comparator.naturalOrder()).orElse(0L);
Or By StreamEx
StreamEx.of(entries.keySet())
.groupingBy(IndexEntry::getWord, summingInt(IndexEntry::getFrequency))
.values().stream().max(Comparator.naturalOrder()).orElse(0L);

Retrieve data from an ArrayList item

Apologies in advance, I am new to Java and I am using someone else's code for the most part so please bear with me. I have looked around but couldn't find anything to help my problem
I've retrieved an ArrayList from a method and then I've attempted to write a foreach loop to retrieve a specific piece of data from what is an 'Observation' below.
For whatever reason it won't allow me to retrieve any of the data stored inside an observation when accessing through the ArrayList.
ArrayList<Observation>[] npcPositions = stateObs.getNPCPositions();
Vector2d playerPosition = stateObs.getAvatarPosition();
int npcCount = npcPositions.length;
for (int i = 0; i <= npcCount; i++)
{
if (playerPosition.x == npcPositions[i].position)
{
}
}
position being a value within the Observation but I get the error that it cannot be resolved or is not a field. Part of the observation class is below and I can not access any of these variables doing what I'm currently doing.
public class Observation implements Comparable<Observation>
{
/**
* Category of this observation (static, resource, npc, etc.).
*/
public int category;
/**
* Type of sprite of this observation.
*/
public int itype;
/**
* unique ID for this observation
*/
public int obsID;
/**
* Position of the observation.
*/
public Vector2d position;
/**
* Reference to the position used for comparing this
* observation with others.
*/
public Vector2d reference;
So what do I need to use to access those variables. I noticed that I have to use [] when I want to store data from stateObs.getNPCPositions and that seems to be the reason why other examples weren't working for me but I am unsure on how to fix it.
UPDATE
The original issue seems to be fixed, however when attempting to retrieve the length of the ArrayList, I get nullpointerexception. How can I get the number of items to be able to run through them in the loop each time.
UPDATE #2
/**
* Returns a list of observations of NPC in the game. As there can be
* NPCs of different type, each entry in the array corresponds to a sprite type.
* Every ArrayList contains a list of objects of type Observation.
* Each Observation holds the position, unique id and
* sprite id of that particular sprite.
*
* #return Observations of NPCs in the game.
*/
public ArrayList<Observation>[] getNPCPositions()
{
return model.getNPCPositions(null);
}
/**
* Returns a list of observations of NPC in the game. As there can be
* NPCs of different type, each entry in the array corresponds to a sprite type.
* Every ArrayList contains a list of objects of type Observation, ordered asc. by
* distance to the reference passed. Each Observation holds the position, sprite type id and
* sprite id of that particular sprite.
*
* #param reference Reference position to use when sorting this array,
* by ascending distance to this point.
* #return Observations of NPCs in the game.
*/
public ArrayList<Observation>[] getNPCPositions(Vector2d reference)
{
return model.getNPCPositions(reference);
}
This:
ArrayList<Observation>[] npcPositions = stateObs.getNPCPositions();
is getting an array of ArrayList. You can get a single ArrayList from index i of the array using:
ArrayList<Observation> list = npcPositions[i];
You can get the Observation at index j of your list using:
Observation obs = list.get(j);
Or you can use them in combination:
Observation obs = npcPositions[i].get(j);
In line:
npcPositions[i].position
Is an array of ArrayList which does not have any property position. Possibly you would try:
npcPositions[i].get(0).position
Edited:
As you said that this line gives NPE:
int npcCount = npcPositions.length;// possibly npcPositions is null
Below line is executed to get the array list:
public ArrayList<Observation>[] getNPCPositions()
{
return model.getNPCPositions(null);//<-- note this, possibly model is also null
}
I am not sure what you are doing in the first two lines of your code, but assumming that what you are doing is correct then the problem lies with your if statement. You are trying to test if a Vector2D.x is equal to a Vector2D which can never happen. try doing this
for(int i = 0; i < npcCount; < i++)
{
if(playerPosition == npcPositions.get(i).position)
{
//do something here
}
}
or you can try this
for(int i = 0; i < npcCount; < i++)
{
if(playerPosition.x == npcPositions.get(i).position.x)
{
//do something here
}
}

JasperReport: How to use subreport return values as input for Main Report Variable Calculation

Scenario:
I've two reports: Main Report (let's call it, A) and sub-report (let's call it, B).
Report A contains sub-report B at the detail band, so sub-report B is displayed for each element at the Report A datasource. Sub-report B also returns a variable to the Main report A.
What I want is to sum those return values from sub-report B and totalize them at the Main report summary.
To do that, I have tried to create a new report variable that sum those returns values... Something like this:
However, I've found that such variables expression are always evaluated before the band detail is rendered, so I always miss the first sub-report return value...
Sadly, the evaluation time (as this link says) cannot be changed on those kind of variables, so I'm stuck...
After been struggling with this for some hours... and searching the internet for a solution... I came with a Workaround (the enlightening forums were these ones: one and two).
First, you need to define a java Class Helper that allows you calculate some arithmetic operation, in my case a Sum operation. I defined these classes:
package reports.utils;
import java.util.Map;
/**
* Utility that allows you to sum Integer values.
*/
public class SumCalculator {
/**
* Stores a map of {#code SumCalculator} instances (A Map instance per thread).
*/
private static final ThreadLocalMap<String, SumCalculator> calculatorsIndex = new ThreadLocalMap<>();
/**
* The sum total.
*/
private int total = 0;
/**
* No arguments class constructor.
*/
private SumCalculator() {
super();
}
/**
* Instance a new {#code SumCalculator} with the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return the new {#code SumCalculator} instance
*/
public static SumCalculator get(String id) {
Map<String, SumCalculator> map = calculatorsIndex.get();
SumCalculator calculator = map.get(id);
if (calculator == null) {
calculator = new SumCalculator();
map.put(id, calculator);
}
return calculator;
}
/**
* Destroy the {#code SumCalculator} associated to the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return {#code null}
*/
public static String destroy(String id) {
Map<String, SumCalculator> map;
map = calculatorsIndex.get();
map.remove(id);
if (map.isEmpty()) {
calculatorsIndex.remove();
}
return null;
}
/**
* Resets the {#code SumCalculator} total.
*
* #return {#code null}
*/
public String reset() {
total = 0;
return null;
}
/**
* Adds the given integer value to the accumulated total.
*
* #param i an integer value (can be null)
* #return {#code null}
*/
public String add(Integer i) {
this.total += (i != null) ? i.intValue() : 0;
return null;
}
/**
* Return the accumulated total.
*
* #return an Integer value (won't be null, never!)
*/
public Integer getTotal() {
return this.total;
}
}
package reports.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Thread Local variable that holds a {#code java.util.Map}.
*/
class ThreadLocalMap<K, V> extends ThreadLocal<Map<K, V>> {
/**
* Class Constructor.
*/
public ThreadLocalMap() {
super();
}
/* (non-Javadoc)
* #see java.lang.ThreadLocal#initialValue()
*/
#Override
protected Map<K, V> initialValue() {
return new HashMap<>();
}
}
Second, at your jasper report, you need to define four text fields:
1) A text field that iniatializes your calculator; it should be (ideally) at the title section of the report and should have an expression like this: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").reset(). This text field should have the evaluation time: NOW.
2) A text field that calls the increment function (i.e. SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").add($V{SUB_REPORT_RETURN_VALUE}). This text field will reside at your detail band, after the subreport element; and it should have the evaluation time: BAND (this is very important!!)
3) A text field that prints the calculator total. This text field will reside at your summary band, it will evaluate to NOW. Its expression will be: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").getTotal()
4) A text field that destroy the calculator. This text field will also reside at your summary band and must appear after the text field 3. The text field should have an expression like: SumCalculator.destroy("$V{SUB_REPORT_RETURN_VALUE}"). This text field should have the evaluation time: NOW.
Also, the text fields: 1, 2, and 4, should have the attribute "Blank when Null", so they will never be printed (that's why those java operations always return null).
And That's it. Then, your report can look something like this:
if i understand the problem, you can not summarize the amount returned by the sub report in the main report, i had the same problem and i solved in this way.
1.- Create a class which extends from net.sf.jasperreports.engine.JRDefaultScriptlet. and override the method beforeReportInit()
this is the code from this class.
package com.mem.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
public class SumarizacionSubtotales extends JRDefaultScriptlet {
private final Log log = LogFactory.getLog(getClass());
private Double total;
public Double getTotal() {
return total;
}
public Double add(Double cantidad) {
if(log.isDebugEnabled())log.debug("AGREGANDO LA CANTIDAD : " + cantidad);
this.total += cantidad;
return cantidad;
}
#Override
public void beforeReportInit() throws JRScriptletException {
if(log.isDebugEnabled())log.debug("beforeReportInit");
total = 0.0D;
}
}
2.- add your project's jar in your ireport's classpath.
3.- Replace the class of the REPORT scriptlet.
in the properties with your class.
3.- add in the group footer where you want to print the value returned by the sub-report a textfield with the following expression.
$P{REPORT_SCRIPTLET}.add( $V{sum_detalles} )
In this case $V{sum_detalles} is a variable in the main report which contains the value returned by the sub-report.
4.- Add in the Last page footer another textfield with the following expression.
$P{REPORT_SCRIPTLET}.getTotal()

GWT Cell tree, how to use?

Can somebody explains how to use the GWT cell tree. I am trying to google it but not finding any valuable tutorial??
Thanks
Try;
Google Example 1
includes onModuleLoad method. :)
For those who don't like the google showcase example like me can use this example;
http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/user/cellview/client/CellTree.html
you can just copy paste it and it works.
"
Trivial example
public class CellTreeExample implements EntryPoint {
/**
* The model that defines the nodes in the tree.
*/
private static class CustomTreeModel implements TreeViewModel {
/**
* Get the {#link NodeInfo} that provides the children of the specified
* value.
*/
public <T> NodeInfo<?> getNodeInfo(T value) {
/*
* Create some data in a data provider. Use the parent value as a prefix
* for the next level.
*/
ListDataProvider<String> dataProvider = new ListDataProvider<String>();
for (int i = 0; i < 2; i++) {
dataProvider.getList().add(value + "." + String.valueOf(i));
}
// Return a node info that pairs the data with a cell.
return new DefaultNodeInfo<String>(dataProvider, new TextCell());
}
/**
* Check if the specified value represents a leaf node. Leaf nodes cannot be
* opened.
*/
public boolean isLeaf(Object value) {
// The maximum length of a value is ten characters.
return value.toString().length() > 10;
}
}
public void onModuleLoad() {
// Create a model for the tree.
TreeViewModel model = new CustomTreeModel();
/*
* Create the tree using the model. We specify the default value of the
* hidden root node as "Item 1".
*/
CellTree tree = new CellTree(model, "Item 1");
// Add the tree to the root layout panel.
RootLayoutPanel.get().add(tree);
}
}
"

Categories