How to set an attribute of Vaadin 8 TextField without getElement method? - attributes

I am writing a filter to filter person names which are displayed in a column pertaining to a vaadin grid. I add a data provider with row objects as follows:
ListDataProvider<Row> dataProvider = new ListDataProvider<>(dataSet.getRows());
Grid.Column<Row, Object> colName = grid.addColumn(row -> row.getValue("NAME")).setCaption("NAME");
grid.setDataProvider(dataProvider);
HeaderRow filterRow = grid.appendHeaderRow();
RowFilter filterObject = new RowFilter();
dataProvider.setFilter(row -> filterObject.test(row, "NAME"));
TextField nameField = new TextField();
nameField.addValueChangeListener(event -> {
filterObject.setName(event.getValue());
dataProvider.refreshAll();
});
nameField.setValueChangeMode(ValueChangeMode.EAGER);
filterRow.getCell(colName).setComponent(nameField);
nameField.setSizeFull();
nameField.setPlaceholder("Filter");
nameField.getElement().setAttribute("focus-target", "");
The row filter looks as follows:
package com.example.vaadin.utils;
import org.apache.commons.lang3.StringUtils;
public class RowFilter {
String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean test(com.example.vaadin.views.ContactView.Row row, String columnval) {
if (name.length() > 0 && !StringUtils
.containsIgnoreCase(String.valueOf(row.getValue(columnval)),
name)) {
return false;
}
return true;
}
}
Here is my row class:
package com.example.vaadin.utils;
import org.apache.commons.lang3.StringUtils;
public class RowFilter {
String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean test(com.example.vaadin.views.ContactView.Row row, String columnval) {
if (name.length() > 0 && !StringUtils
.containsIgnoreCase(String.valueOf(row.getValue(columnval)),
name)) {
return false;
}
return true;
}
}
The problem is the following one:
When I want to add the attribute focus-target to the nameField like this - nameField.getElement().setAttribute("focus-target", ""); - but com.vaadin.ui.TextField does not seem to have a getElement method in vaadin 8. I have been looking for a workaround to get this problem fixed, but to no avail. This is why I’d like to ask here whether anybody can tell me if there is one.

getElement() was added in Vaadin 10 and is not included in Vaadin 8. There is no built-in way of setting arbitrary attributes in Vaadin 8, so you would instead have to take to low-level solutions such as building a simple client-side extension or using Javascript::execute.

Related

Using a string to specify an object in Java

I have a Combo Bx (Dropdown box) with an index range of 0-20. If there anyways I can use that index to specify which object I want data from? All of the objects use the same naming convention obj0, obj1, obj2, etc. Basically something like this...
public abstract class Person {
private String name;
private String title;
private String email;
private String job;
public Person(String name, String title, String email, String job){
this.name = name;
this.title = title;
this.email = email;
this.job = job;
}
//Getters and Setters
}
public class main extends javax.swing.JFrame {
...misc code...
private void btn_startActionPerformed(java.awt.event.ActionEvent evt) {
Person obj0 = new Person("Jon Doe",
"Program Coordinator",
"jon.doe#test.com",
"Faculty");
Person obj1 = ...
...
Person obj20 = ...
/*
Onclick it uses the index of the current index in the combobox (dropdown)
to specify which object to get the data from.
*/
private void btn_GetActionPerformed(java.awt.event.ActionEvent evt) {
//Uses the obj naming convention plus the index
string foo = "obj" + toString(combobox_Name.getSelectedIndex());
//Fills the textbox using the above string and the getName method
txtbox_username.setText(ToObject(foo).getName);
}
I have created a basic design of what I think you want:
This code creates 20 objects, adds them to a combobox and uses their predefined name when selected to change a textfield.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
class ObjExample {
String name;
public ObjExample(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
public class Main extends JFrame implements ActionListener {
JComboBox jcb = new JComboBox();
JTextField jtf = new JTextField("Text Field");
public Main() {
setSize(200, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int i = 0; i <= 20; i++) {
jcb.addItem(new ObjExample(Integer.toString(i)));
}
jcb.addActionListener(this);
add(jcb);
add(jtf);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jcb) {
ObjExample obj = (ObjExample) jcb.getSelectedItem();
jtf.setText(obj.toString());
}
}
}

Loading overlay never disappears in config of Jenkins plugin

I want to add repeatable properties to the Jenkins plugin I'm developing, and created a test plugin to make make sure I was using them correctly. My plugin seems to work fine, I can add as many properties as I want when I originally edit the config, and it saves and builds. However, when I try to edit the config a second time, the config screen shows the loading overlay endlessly. If I scroll down, I can see the properties I saved earlier are still there, but I can't edit anything.
My class looks like this:
public class RepeatableTest extends Builder {
private List<Prop> property = new ArrayList<Prop>();
#DataBoundConstructor
public RepeatableTest(List<Prop> property) {
this.property = property;
}
public List<Prop> getProperty() {
return property;
}
#Override
public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException {
listener.getLogger().println(property.get(0).name);
listener.getLogger().println(property.size());
return true;
}
#Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
public static class Prop extends AbstractDescribableImpl<Prop> {
public String name;
public String getName(){
return name;
}
#DataBoundConstructor
public Prop(String name) {
this.name = name;
}
#Extension
public static class DescriptorImpl extends Descriptor<Prop> {
#Override
public String getDisplayName() {
return "";
}
}
}
#Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
private String phpLoc;
public DescriptorImpl() {
load();
}
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// Indicates that this builder can be used with all kinds of project types
return true;
}
public String getDisplayName() {
return "Repeatable Test";
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
phpLoc = formData.getString("phpLoc");
save();
return super.configure(req,formData);
}
public String getPhpLoc() {
return phpLoc;
}
}
}
My config.groovy looks like this:
package uitestplugin.uitest.RepeatableTest;
import lib.JenkinsTagLib
import lib.FormTagLib
def f = namespace(lib.FormTagLib)
t=namespace(JenkinsTagLib.class)
f.form{
f.entry(title:"Properties"){
f.repeatableProperty(field:"property")
}
}
and my prop/config.groovy looks like this:
package uitestplugin.uitest.RepeatableTest.Prop;
def f = namespace(lib.FormTagLib)
f.entry(title:"Name", field:"name") {
f.textbox()
}
The config.xml:
<?xml version='1.0' encoding='UTF-8'?>
<project>
<actions/>
<description></description>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<uitestplugin.uitest.RepeatableTest plugin="ui-test#1.0-SNAPSHOT">
<property>
<uitestplugin.uitest.RepeatableTest_-Prop>
<name>Prop1</name>
</uitestplugin.uitest.RepeatableTest_-Prop>
<uitestplugin.uitest.RepeatableTest_-Prop>
<name>Prop2</name>
</uitestplugin.uitest.RepeatableTest_-Prop>
</property>
</uitestplugin.uitest.RepeatableTest>
</builders>
<publishers/>
<buildWrappers/>
</project>
Any ideas as to what could cause this? I based a lot of the code from the ui-samples plugin (https://wiki.jenkins-ci.org/display/JENKINS/UI+Samples+Plugin).
EDIT: The current status of this is, well, I still haven't figured it out. I've done more research and tried tons of different examples, but the farthest I ever get is what I described above. It almost seems like you can't use repeatable through groovy. Anyways, I have one more piece of information to add. Using the web developer toolbar for Firefox, I can see that there is a Javascript error on the page. The error is:
Timestamp: 10/3/2014 12:58:49 PM
Error: TypeError: prototypes is undefined
Source File: http://localhost:8080/adjuncts/e58fb488/lib/form/hetero-list/hetero-list.js
Line: 16
And the code this relates to is(I've marked line 16 with a comment at the end of the line):
// #include lib.form.dragdrop.dragdrop
// do the ones that extract innerHTML so that they can get their original HTML before
// other behavior rules change them (like YUI buttons.)
Behaviour.specify("DIV.hetero-list-container", 'hetero-list', -100, function(e) {
e=$(e);
if(isInsideRemovable(e)) return;
// components for the add button
var menu = document.createElement("SELECT");
var btns = findElementsBySelector(e,"INPUT.hetero-list-add"),
btn = btns[btns.length-1]; // In case nested content also uses hetero-list
YAHOO.util.Dom.insertAfter(menu,btn);
var prototypes = $(e.lastChild);
while(!prototypes.hasClassName("prototypes")) //LINE 16, ERROR IS HERE
prototypes = prototypes.previous();
var insertionPoint = prototypes.previous(); // this is where the new item is inserted.
// extract templates
var templates = []; var i=0;
$(prototypes).childElements().each(function (n) {
var name = n.getAttribute("name");
var tooltip = n.getAttribute("tooltip");
var descriptorId = n.getAttribute("descriptorId");
menu.options[i] = new Option(n.getAttribute("title"),""+i);
templates.push({html:n.innerHTML, name:name, tooltip:tooltip,descriptorId:descriptorId});
i++;
});
Element.remove(prototypes);
var withDragDrop = initContainerDD(e);
var menuAlign = (btn.getAttribute("menualign")||"tl-bl");
var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu, menualignment: menuAlign.split("-") });
$(menuButton._button).addClassName(btn.className); // copy class names
$(menuButton._button).setAttribute("suffix",btn.getAttribute("suffix"));
menuButton.getMenu().clickEvent.subscribe(function(type,args,value) {
var item = args[1];
if (item.cfg.getProperty("disabled")) return;
var t = templates[parseInt(item.value)];
var nc = document.createElement("div");
nc.className = "repeated-chunk";
nc.setAttribute("name",t.name);
nc.setAttribute("descriptorId",t.descriptorId);
nc.innerHTML = t.html;
$(nc).setOpacity(0);
var scroll = document.body.scrollTop;
renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() {
function findInsertionPoint() {
// given the element to be inserted 'prospect',
// and the array of existing items 'current',
// and preferred ordering function, return the position in the array
// the prospect should be inserted.
// (for example 0 if it should be the first item)
function findBestPosition(prospect,current,order) {
function desirability(pos) {
var count=0;
for (var i=0; i<current.length; i++) {
if ((i<pos) == (order(current[i])<=order(prospect)))
count++;
}
return count;
}
var bestScore = -1;
var bestPos = 0;
for (var i=0; i<=current.length; i++) {
var d = desirability(i);
if (bestScore<=d) {// prefer to insert them toward the end
bestScore = d;
bestPos = i;
}
}
return bestPos;
}
var current = e.childElements().findAll(function(e) {return e.match("DIV.repeated-chunk")});
function o(did) {
if (Object.isElement(did))
did = did.getAttribute("descriptorId");
for (var i=0; i<templates.length; i++)
if (templates[i].descriptorId==did)
return i;
return 0; // can't happen
}
var bestPos = findBestPosition(t.descriptorId, current, o);
if (bestPos<current.length)
return current[bestPos];
else
return insertionPoint;
}
(e.hasClassName("honor-order") ? findInsertionPoint() : insertionPoint).insert({before:nc});
if(withDragDrop) prepareDD(nc);
new YAHOO.util.Anim(nc, {
opacity: { to:1 }
}, 0.2, YAHOO.util.Easing.easeIn).animate();
Behaviour.applySubtree(nc,true);
ensureVisible(nc);
layoutUpdateCallback.call();
},true);
});
menuButton.getMenu().renderEvent.subscribe(function() {
// hook up tooltip for menu items
var items = menuButton.getMenu().getItems();
for(i=0; i<items.length; i++) {
var t = templates[i].tooltip;
if(t!=null)
applyTooltip(items[i].element,t);
}
});
if (e.hasClassName("one-each")) {
// does this container already has a ocnfigured instance of the specified descriptor ID?
function has(id) {
return Prototype.Selector.find(e.childElements(),"DIV.repeated-chunk[descriptorId=\""+id+"\"]")!=null;
}
menuButton.getMenu().showEvent.subscribe(function() {
var items = menuButton.getMenu().getItems();
for(i=0; i<items.length; i++) {
items[i].cfg.setProperty("disabled",has(templates[i].descriptorId));
}
});
}
});
Behaviour.specify("DIV.dd-handle", 'hetero-list', -100, function(e) {
e=$(e);
e.on("mouseover",function() {
$(this).up(".repeated-chunk").addClassName("hover");
});
e.on("mouseout",function() {
$(this).up(".repeated-chunk").removeClassName("hover");
});
});
I hope this is enough information to solve the problem. Any suggestions (even if they aren't complete answers) are really appreciated.
While not an exact answer, I did find a way to get this working. For some reason, putting the repeatableProperty in an advanced block stopped the javascript error from happening, so everything loaded fine.
So, my config.groovy for RepeatableTest looked like this:
package uitestplugin.uitest.RepeatableTest;
f = namespace(lib.FormTagLib)
f.advanced{
f.entry(title:"Properties"){
f.repeatableProperty(field:"property", minimum:"1"){
}
}
}
My config.groovy for Prop1 looked like this:
package uitestplugin.uitest.Prop1;
def f = namespace(lib.FormTagLib)
f.entry(title:"Name",field:"name") {
f.textbox()
}
f.entry {
div(align:"left") {
input(type:"button",value:"Delete",class:"repeatable-delete")
}
}
My prop 1 looked like this:
public class Prop1 extends AbstractDescribableImpl<Prop1> {
private final String name;
public String getName(){
return name;
}
#DataBoundConstructor
public Prop1( String name) {
this.name = name;
}
#Extension
public static class DescriptorImpl extends Descriptor<Prop1> {
#Override
public String getDisplayName() {
return "";
}
}
}
And my RepeatableTest.java looked like this:
public class RepeatableTest extends Builder {
private final List<Prop1> property;
// Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
#DataBoundConstructor
public RepeatableTest(List<Prop1> property) {
this.property = property;
}
public List<Prop1> getProperty() {
return property;
}
#Override
public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException {
//Doesn't matter
}
#Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
#Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
private String phpLoc;
public DescriptorImpl() {
load();
}
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// Indicates that this builder can be used with all kinds of project types
return true;
}
public String getDisplayName() {
return "Repeatable Test";
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
phpLoc = formData.getString("phpLoc");
save();
return super.configure(req,formData);
}
public String getPhpLoc() {
return phpLoc;
}
}
}

How to apply mask formatting to TextField?

I am creating some forms and I need to create masks and validation for some fields.
Is it implemented in anyway in JavaFX?
My example of the mask.
Using:
<MaskField mask="+7(DDD)DDD-DDDD"/>
<MaskField mask="AA DDD AAA" placeholder="__ ### ___"/>
etc
Restricting input from Richard's fxexperience post:
TextField field = new TextField() {
#Override public void replaceText(int start, int end, String text) {
// If the replaced text would end up being invalid, then simply
// ignore this call!
if (!text.matches("[a-z]")) {
super.replaceText(start, end, text);
}
}
#Override public void replaceSelection(String text) {
if (!text.matches("[a-z]")) {
super.replaceSelection(text);
}
}
};
If you want to create your use a mask and create your own control, take a look at Richard's MoneyField, which also includes a sample project and source. Along the same lines there are controls to restict input to Integers, Doubles or formatted web colors (e.g. #rrggbb) in the fxexperience repository. All of these follow a common theme where they subclass Control, provide some properties to be get and set which define the public interface and then also define a private backing skin which handles rendering of the UI based on the values set through the public interface.
I had the same needs. I created this field, called it SpecialTextField, and pushed into GitHub. Example also there. Hope this help.
NOTE: this only works correctly with JRE 1.8.0_25 or lower. With JRE 1.8.0_48 or 0_51, the caret position is always set to 0 after each character input.
No, this is not implemented in standard JavaFX. You need to use some library or do it yourself.
This is my implementation of static mask for text fields. It works for date, phone and other types of static masks:
/**
* Adds a static mask to the specified text field.
* #param tf the text field.
* #param mask the mask to apply.
* Example of usage: addMask(txtDate, " / / ");
*/
public static void addMask(final TextField tf, final String mask) {
tf.setText(mask);
addTextLimiter(tf, mask.length());
tf.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
String value = stripMask(tf.getText(), mask);
tf.setText(merge(value, mask));
}
});
tf.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(final KeyEvent e) {
int caretPosition = tf.getCaretPosition();
if (caretPosition < mask.length()-1 && mask.charAt(caretPosition) != ' ' && e.getCode() != KeyCode.BACK_SPACE && e.getCode() != KeyCode.LEFT) {
tf.positionCaret(caretPosition + 1);
}
}
});
}
static String merge(final String value, final String mask) {
final StringBuilder sb = new StringBuilder(mask);
int k = 0;
for (int i = 0; i < mask.length(); i++) {
if (mask.charAt(i) == ' ' && k < value.length()) {
sb.setCharAt(i, value.charAt(k));
k++;
}
}
return sb.toString();
}
static String stripMask(String text, final String mask) {
final Set<String> maskChars = new HashSet<>();
for (int i = 0; i < mask.length(); i++) {
char c = mask.charAt(i);
if (c != ' ') {
maskChars.add(String.valueOf(c));
}
}
for (String c : maskChars) {
text = text.replace(c, "");
}
return text;
}
public static void addTextLimiter(final TextField tf, final int maxLength) {
tf.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
if (tf.getText().length() > maxLength) {
String s = tf.getText().substring(0, maxLength);
tf.setText(s);
}
}
});
}
See also:
JavaFX 2.2 TextField maxlength
Supported by current javafx-2 platform by default - No, but go through this link , it has many insights and sample code for Form validation in javaFX
public class NumberTextField extends TextField {
private int maxLenght;
public NumberTextField(int maxLenght) {
super();
this.maxLenght = maxLenght;
}
#Override
public void replaceText(int start, int end, String text) {
if (validate(text)) {
super.replaceText(start, end, text);
}
}
#Override
public void replaceSelection(String text) {
if (validate(text)) {
super.replaceSelection(text);
}
}
private boolean validate(String text) {
if (this.getText() != null) {
}
boolean status = ("".equals(text) || text.matches("[0-9]"));
if (this.getText() == null) {
return status;
} else {
return (status && this.getText().length() < maxLenght);
}
}
}
In some cases I would validate the text property:
myTextField
.textProperty()
.addListener(
(obs, oldVal, newVal) ->
{
if(!newVal.matches("\\d+"))
textField.setText(oldV);
});
Unlucky: textField.setText(oldV); will enter the same function again, testing unnecessarily if oldVal matches.
If the TextField becomes a value that doesn't matches before this listener is added to the TextField, enter a not matching new value will cause a loop!!!
To avoid this, it will be safer to write:
String acceptableValue = "0";
myTextField
.textProperty()
.addListener(
(obs, oldVal, newVal) ->
{
if(!newVal.matches("\\d+"))
textField.setText(oldVal.matches("\\d+") ? oldV : acceptableValue);
});
I wrote a class that extends the TextField and apply the mask.
package com.model;
import java.text.NumberFormat;
import java.util.Locale;
/**
* ATENTION
* DO NOT FORGUET TO IMPORT IN FXML
* <?import com.view.TextFieldMoney?>
*
* */
import javafx.scene.control.TextField;
public class TextFieldMoney extends TextField {
private int maxlength;
private String valor = "";
public TextFieldMoney() {
this.maxlength = 11;
}
public void setMaxlength(int maxlength) {
this.maxlength = maxlength;
}
#Override
public void replaceText(int start, int end, String text) {
// Delete or backspace user input.
if (getText() == null || getText().equalsIgnoreCase("")) {
valor = "";
}
if (text.equals("")) {
super.replaceText(start, end, text);
} else{
text = text.replaceAll("[^0-9]", "");
valor += text;
super.replaceText(start, end, text);
if (!valor.equalsIgnoreCase(""))
setText(formata(valor));
}
}
#Override
public void replaceSelection(String text) {
// Delete or backspace user input.
if (text.equals("")) {
super.replaceSelection(text);
} else if (getText().length() < maxlength) {
// Add characters, but don't exceed maxlength.
// text = MascaraFinanceira.show(text);
if (text.length() > maxlength - getText().length()) {
// text = MascaraFinanceira.show(text);
text = text.substring(0, maxlength - getText().length());
}
super.replaceSelection(text);
}
}
/*
*Return the number without money mask
**/
public String getCleanValue(){
String cleanString = getText().replaceAll("[^0-9]", "");
Double cleanNumber = new Double(cleanString);
return String.valueOf(cleanNumber/100);
}
private String formata(Double valor) {
Locale locale = new Locale("pt", "BR");
NumberFormat nf = NumberFormat.getInstance(locale);
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
return nf.format(valor);
}
public String formata(String valor) {
double v = new Double(valor);
return formata(v/100);
}
}
And in the FXML where is
<TextField fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />
put
<TextFieldMoney fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />

Array List in C# without a loop

I like to know how to initialise the array without the loops like for, foreach or any LINQ.
From the following code, need to find under 2m length cars within .Netframework using console application.
{
ArrayList = CarType new ArrayList();
CarType.Add(new CarList("Ford"));
((CarList)CarType[0]).Cars.Add(new Car("Focus", 2));
((CarList)CarType[0]).Cars.Add(new Car("Fiesta", 1));
CarType.Add(new CarList("Peugeout"));
((CarList)CarType[1]).Cars.Add(new Car("206", 1));
((CarList)CarType[1]).Cars.Add(new Car("407", 2));
RemoveLargeCars(CarType);
}
public static ArrayList RemoveLargeCars (ArrayList CarType)
{
//Array List should be here
return CarType;
}
It has got two classes as follows.
class Car
{
public string name;
public float length;
public Car(string newName, float newLength)
{
this.name = newName;
this.length = newLength;
}
}
Class CarList
{
public string CarType;
public ArrayList Pipes;
public CarList(string newCarType)
{
carType = newCarType;
Cars = new ArrayList();
}
}
Can you please let me know how to solve this.
Thanks in advance.
Use the static Adapter method on ArrayList
CarType = ArrayList.Adapter(CarList);
But that probably uses a loop internally, you can't get away from them, but at least this hides them.
Well, first of all you should use the generic list type List<T> instead of ArrayList, that will make the code simpler. (And best practive recommends properties rather than public fields):
class Car {
public string Name { get; set; }
public float Length { get; set; }
public Car(string newName, float newLength) {
Name = newName;
Length = newLength;
}
}
class CarList {
public string CarType { get; set; }
public List<Car> Cars { get; set; }
public CarList(string newCarType, List<Car> newCars) {
CarType = newCarType;
Cars = newCars;
}
public CarList(string newCarType) : this(newCarType, new List<Car>()) {}
}
Now use a List<CarList>:
List<CarList> CarType = new List<CarList>();
CarList ford = new CarList("Ford");
CarType.Add(ford);
ford.Cars.Add(new Car("Focus", 2));
ford.Cars.Add(new Car("Fiesta", 1));
CarList peugeot = new CarList("Peugeout");
CarType.Add(peugeot);
peugeot.Cars.Add(new Car("206", 1));
peugeot.Cars.Add(new Car("407", 2));
List<CarList> smallCars = RemoveLargeCars(CarType);
You can use extension methods to easily filter out cars based on a condition:
public static List<CarList> RemoveLargeCars(List<CarList> CarType) {
return CarType.Select(
t => new CarList(t.CarType, t.Cars.Where(c => c.Length < 2f).ToList()
) .ToList();
}
Note that the method doesn't change the original list, but creates a new list.

Nesting Maps in Java

I want to store many details (like name, email, country) of the particular person using the same key in hashtable or hashmap in java?
hashMap.put(1, "Programmer");
hashMap.put(2, "IDM");
hashMap.put(3,"Admin");
hashMap.put(4,"HR");
In the above example, the 1st argument is a key and 2nd argument is a value, how can i add more values to the same key?
You can achieve what you're talking about using a map in each location of your map, but it's a little messy.
Map<String, Map> people = new HashMap<String, Map>();
HashMap<String, String> person1 = new HashMap<String, String>();
person1.put("name", "Jones");
person1.put("email", "jones#jones.com");
//etc.
people.put("key", person1);
//...
people.get("key").get("name");
It sounds like what you might really want, though, is to define a Person class that has multiple properties:
class Person
{
private String name;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//plus getters and setters for other properties
}
Map<String, Person> people = new HashMap<String, Person>();
person1 = new Person();
person1.setName("Jones");
people.put("key", person1);
//...
people.get("key").getName();
That's the best I can do without any information about why you're trying to store values in this way. Add more detail to your question if this is barking up the wrong tree.
I think what you are asking
let us assume you we want to store String page, int service in the key and an integer in the value.
Create a class PageService with the required variables and define your HashMap as
Hashmap hmap = .....
Inside pageService, what you need to do is override the equals() and hashcode() methods. Since when hashmap is comparing it checks for hashcode and equals.
Generating hashcode and equals is very easy in IDEs. For example in eclipse go to Source -> generate hashcode() and equals()
public class PageService {
private String page;
private int service;
public PageService(String page, int service) {
super();
this.page = page;
this.service = service;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public int getService() {
return service;
}
public void setService(int service) {
this.service = service;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((page == null) ? 0 : page.hashCode());
result = prime * result + service;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PageService other = (PageService) obj;
if (page == null) {
if (other.getPage() != null)
return false;
} else if (!page.equals(other.getPage()))
return false;
if (service != other.getService())
return false;
return true;
}
}
The following class is very generic. You can nest ad infinitum. Obviously you can add additional fields and change the types for the HashMap. Also note that the tabbing in the toString method should be smarter. The print out is flat.
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HierarchicalMap
{
private String key;
private String descriptor;
private Map<String,HierarchicalMap>values=new HashMap<String,HierarchicalMap>();
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public void addToSubMap(String key, HierarchicalMap subMap)
{
values.put(key, subMap);
}
public String getDescriptor()
{
return descriptor;
}
public void setDescriptor(String descriptor)
{
this.descriptor = descriptor;
}
public HierarchicalMap getFromSubMap(String key)
{
return values.get(key);
}
public Map<String,HierarchicalMap> getUnmodifiableSubMap()
{
return Collections.unmodifiableMap(values);
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("HierarchicalMap: ");
sb.append(key);
sb.append(" | ");
sb.append(descriptor);
Iterator<String> itr=values.keySet().iterator();
while(itr.hasNext())
{
String key= itr.next();
HierarchicalMap subMap=this.getFromSubMap(key);
sb.append("\n\t");
sb.append(subMap.toString());
}
return sb.toString();
}

Resources