I have data like in following logical format:
FolderID-1
FileID-1
FileID-2
FolderID-2
FileID-3
FileID-4
FileID-5
FileID-6
FolderID-3
FileID-7
FileID-8
FileID-9
FileID-10
I have list of FileID object which have FoldeID
I need to update one field in this list and need to pass to this list in other method.
I need to get FileID object based on fileid & folderid in that method.
To achieve the same I know two way
1 HashMap<folderid,List<FileID>> OR
2 HashMap<folderid, HashMap<fileid ,FileID>
Is there any other efficient way to do the same?
Thanks for looking here.
Hi I read your cmnt you can go ahead with the string key (using fileid and folder id) that will work for you. But your data comes with a nice logical structure . file id and folder id will be unique as well as a single folder will contain file having the file id is consecutive. So, My approach to solve this entirely depends on this structure.
I made two Class FileIdObj and FolderIdObj thats contains the data redarding the file and folder respectively.
public static void fileIdBasedOnFileIdAndFolderId( List<FileIdObj> fileList)
{
Map<Integer,FolderIdObj> folderIdMap=new HashMap<Integer,FolderIdObj>();
Map<Integer,FileIdObj> fileIdMap=new HashMap<Integer,FileIdObj>();
for(int i=0;i<fileList.size();i++)
{
FileIdObj file=fileList.get(i);
fileIdMap.put(file.getFileId(), file);
int folderId=file.getFolderId();
FolderIdObj folder=new FolderIdObj();
if(folderIdMap.containsKey(folderId))
{
folder=folderIdMap.get(folderId);
folder.setEndFileId(file.getFileId());
}else
{
folder.setFolderId(folderId);
folder.setStartFileId(file.getFileId());
folder.setEndFileId(file.getFileId());
}
folderIdMap.put(folderId, folder);
}
Set<Integer> set=folderIdMap.keySet();
Iterator it=set.iterator();
while(it.hasNext())
{
FolderIdObj obj=folderIdMap.get(it.next());
System.out.println("folder id: "+obj.getFolderId()+" start fileId: "+obj.getStartFileId()+
" end fileId: "+obj.getEndFileId());
}
System.out.println();
System.out.println();
set=fileIdMap.keySet();
it=set.iterator();
while(it.hasNext())
{
FileIdObj obj=fileIdMap.get(it.next());
System.out.println("file id: "+obj.getFileId()+" folder id:"+obj.getFolderId());
}
}
the list on the argument contains the file object only.
Please see below for the details of the two class.
public class FileIdObj {
private int folderId;
private int fileId;
public int getFolderId() {
return folderId;
}
public void setFolderId(int folderId) {
this.folderId = folderId;
}
public int getFileId() {
return fileId;
}
public void setFileId(int fileId) {
this.fileId = fileId;
}
}
public class FolderIdObj {
private int folderId;
private int startFileId;
private int endFileId;
public int getFolderId() {
return folderId;
}
public void setFolderId(int folderId) {
this.folderId = folderId;
}
public int getStartFileId() {
return startFileId;
}
public void setStartFileId(int startFileId) {
this.startFileId = startFileId;
}
public int getEndFileId() {
return endFileId;
}
public void setEndFileId(int endFileId) {
this.endFileId = endFileId;
}
}
Related
I will keep it simple and easy for you guys to help me out , this is the example testfile i want to "populate" with data in this way:
1,Justinianos,Maia,2
2,Hulks,Famalicao,5
3,Padres Matias,Porto,12
4,Fanadinhos,Lisboa,4
5,Melancolitos,Vila Nova de Gaia,6
6,Ao Colinho,Sao Romao,7
7,Cavalos do Zodiaco,Cabecas de bastos,10
8,Unicorns,Aveiro,2
9,Rainbows,Coimbra,3
10,One Piece 4 ever,Folgosa,15
id,nomequadra,localidade,qtdcavalos
int,String,String,int
Then this is the class that stores the data:
/**
* Created by Ricar on 02/04/2017.
*/
public class Quadras {
private int id;
private String nomequadra;
private String localidade;
private int qtdcavalos;
public Quadras(){
id=0;
nomequadra=null;
localidade=null;
qtdcavalos=0;
}
public Quadras(int id , String nomequadra, String localidade, int qtdcavalos){
this.id = id;
this.nomequadra = nomequadra;
this.localidade = localidade;
this.qtdcavalos = qtdcavalos;
}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getNomequadra() {return nomequadra;}
public void setNomequadra(String nomequadra) {this.nomequadra = nomequadra;}
public String getLocalidade() {return localidade;}
public void setLocalidade(String localidade) {this.localidade = localidade;}
public int getQtdcavalos() {return qtdcavalos;}
public void setQtdcavalos(int qtdcavalos) {this.qtdcavalos = qtdcavalos;}
}
This other class joins together all the classes into arraylist for working with the data:
public class Championship {
private ArrayList<Quadras> quadras;
private ArrayList<Participante> participantes;
private ArrayList<Jornada> jornadas;
public Championship(){
this.quadras = new ArrayList<Quadras>();
this.jornadas = new ArrayList<Jornada>();
this.participantes = new ArrayList<Participante>();
}
public Championship(ArrayList<Quadras> quadras, ArrayList<Participante> participantes, ArrayList<Jornada> jornadas)
{
this.quadras = quadras;
this.participantes = participantes;
this.jornadas = jornadas;
}
public void addQuadras (Quadras s ) {quadras.add(s);}
public void printQuadras(){
System.out.println("--------Quadras-------");
for(int i = 0; i< quadras.size();i++){
System.out.println(quadras.get(i));
}
}
public void addParticipantes (Participante s ) {participantes.add(s);}
public void addJornada (Jornada s ) {jornadas.add(s);}
}
I want to populate the Championship Arraylist ,using split on the "," and then convert each substring that has difrent data then string like Integer.
After that i want to be able to reverse the process also, because i will be inserting data manualy into the txt file, but i want to be able to load from the file and store in the file.
I already have a createnewFile(); method and deleteFile(); method.
If someone could five me a hand here i would be very happy :)
Thx for spending thime reading my problem!
You can check if is a digit or a number using the code in this link:
What is the best way to tell if a character is a letter or number in Java without using regexes?
After, you can populate your objects.
Hope it helps
I'm trying to read a csv and storing the records in an ArrayList.
Since I know the no. of records in the csv file I'm specifying the size i.e. 600 when creating the object.
I want the program to be able to read files of unknown no. of records.
How do I make it dynamic.
Here's the working code for the file with 600 records.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.*;
public class BankRecords extends Client{
//Create objects for processing data
//private static int count;
static BankRecords[] obj=new BankRecords[600];
static List<List<String>> array = new ArrayList<List<String>>();
#Override
void readData() {
// TODO Auto-generated method stub
String line=" ";
//int i=0;
//try with resources statement
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
array.add(Arrays.asList(line.split(",")));
//check data
//count++;
//System.out.println(array.get(i++));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
processData();
}
#Override
void processData() {
// TODO Auto-generated method stub
int idx=0;
for(List<String> bankData: array)
{
obj[idx]= new BankRecords();
obj[idx].setId(bankData.get(0));
obj[idx].setAge(Integer.parseInt(bankData.get(1)));
obj[idx].setSex(bankData.get(2));
obj[idx].setRegion(bankData.get(3));
obj[idx].setIncome(Double.parseDouble(bankData.get(4)));
obj[idx].setMarried(bankData.get(5));
obj[idx].setChild(Integer.parseInt(bankData.get(6)));
obj[idx].setCar(bankData.get(7));
obj[idx].setSact(bankData.get(8));
obj[idx].setCact(bankData.get(9));
obj[idx].setMort(bankData.get(10));
obj[idx].setPep(bankData.get(11));
idx++;
//System.out.println(obj[idx].getId());
}
printData();
}
#Override
void printData() {
//Printing First 25 ID, age, sex, region, income and mortgage
System.out.println("ID\t\tAGE\t\tSEX\t\tREGION\t\tINCOME\t\tMORTGAGE\n");
for(int i=0;i<25;i++){
String s=String.format("%s\t\t%s\t\t%s\t\t%-10s\t%8.2f\t%2s", obj[i].getId(),obj[i].getAge(),obj[i].getSex(),obj[i].getRegion(),obj[i].getIncome(),obj[i].getMort());
System.out.println(s);
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public String isMarried() {
return married;
}
public void setMarried(String married) {
this.married = married;
}
public int getChild() {
return child;
}
public void setChild(int child) {
this.child = child;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getSact() {
return sact;
}
public void setSact(String sact) {
this.sact = sact;
}
public String getCact() {
return cact;
}
public void setCact(String cact) {
this.cact = cact;
}
public String getMort() {
return mort;
}
public void setMort(String mort) {
this.mort = mort;
}
public String getPep() {
return pep;
}
public void setPep(String pep) {
this.pep = pep;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BankRecords bnk= new BankRecords();
bnk.readData();
}
}
ArrayList can the elements dynamically, so it is not required to know the size in advance.
However, for the BankRecords array, do not initialize it with 600 initially. Instead do something like this:
static BankRecords[] obj = null;
static List<List<String>> array = new ArrayList<List<String>>();
void processData() {
// TODO Auto-generated method stub
obj=new BankRecords[array.size()];
// TODO do your work here
}
You do not have to know the number of records beforehand in order to use an ArrayList. You can specify a default size in the constructor, however it is smart enough to expand itself if you add more records than this.
You are almost there, but for some strange reasons you are using Lists in places where you already have an array; yet on the other side, you are using an array where a List would be a much better fit.
You can rework your code as follows:
// TODO Auto-generated method stub
HINT: those TODOs are generated by your IDE. The idea is that you delete them as soon as you have some real content instead. Keeping them means leaving garbage in your source code. Anything that doesn't add real value to your source code: remove it. Always. Immediately!
String line=" ";
List<Bankrecord> records = new ArrayList<>();
//int i=0; ... again: unused code --- remove that!
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
String[] lineData = line.split(",");
BankRecord recordForNewLine = buildRecordFrom(lineData);
records.add(recordForNewLine);
} ...
And then you could rework your processData into something like:
private BankRecord buildRecordFrom(String[] lineData) {
BankRecord newRecord = new BankRecords();
newRecord.setId(lineData[0];
...
return newRecord;
}
And things that you should really consider changing, too:
Building your bank records by simply assuming that column contains a valid ID, and the next column contains a valid xyz ... is a bad idea.
Instead, you should be validating all your input: you should check that each array you gain from split has **exactly the expected length. And then have to validate that each value from that array has the expected "content"
Then, from a modelling perspective: you have a ton of setters on your Bankrecord class. But that is simply wrong! In real life, when some "record" is created, then its essential properties (such as its ID) can't be changed after creation!
Instead, you should make sure that such properties in your class can't be changed after the object has been created. The way to go here: Builder pattern!
Finally: my code above is meant as "inspiration point" to get you going. Dont blindly copy/paste it; there might be various typos in - just read it until you get what (and why) it is doing (what it is doing)!
Then: I hope you understand that real CSV parsing is much more complicated than splitting around "," (for example: strings in CSV data can contain ',' too; and then your simple split would rip up that string!)
If you are serious about parsing real-world-other-people CSV input, then you better look into using existing libraries to do this for you. Writing a correct CSV parser is hard work (and not very rewarding; since that means re-inventing a complicated wheel for no good reason)!
I've got a project written in JavaFX and I'm trying to get a refresh on a tableview without result.
I've googled around and tried some examples I've found but it still doesn't work.
I populate a tableview with information each row in this table can have new comments added to by double click on the row. The a new Tabpane is opened and the new comment can be added there. On close of this tabpane I'd like the one I clicked from to be refreshed.
I must be doing something wrong. I just don't know what.
In my StoreController
private void populateTableView(List<Store> stores) {
ObservableList<Store> data = FXCollections.observableArrayList(stores);
storeNumberColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("id"));
storePhoneColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("phoneNbr"));
chainColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("chainId"));
commentColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Store, ImageView>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Store, ImageView> p) {
Integer numberOfComments = p.getValue().getCommentsCount();
ReadOnlyObjectWrapper wrapper = null;
if (numberOfComments == 0) {
wrapper = null;
} else if (numberOfComments == 1) {
wrapper = new ReadOnlyObjectWrapper(new ImageView(COMMENT_SINGLE_FLAG_SOURCE));
} else {
wrapper = new ReadOnlyObjectWrapper(new ImageView(COMMENT_DOUBLE_FLAG_SOURCE));
}
return wrapper;
}
});
storeTable.setItems(data);
sortTable(storeTable, missedColumn);
}
#FXML
public void handleTableAction(MouseEvent event) {
if (event.getClickCount() == 2) {
showNewCommentStage();
}
}
private void showNewCommentStage() {
initCommentController();
Store store
= storeTable.getSelectionModel().selectedItemProperty().getValue();
commentController.showNewStage(commentPane, store);
}
It seems like the call-function doesn't get called when the commentpane is closed.
CommentController
public void showNewStage(Pane pane, Store store) {
this.store = store;
initStage(pane);
windowHandler = new WindowHandler(stage);
effectHandler.playEffect(pane);
constructCommentHeaders();
List<Comment> comments;
comments = commentService.listByStoreId(store.getId());
populateCommentTable(comments);
}
Like I said I've tried a lot of the solutions found here on Stackoverflow but with no results. The Tableview doesn't refresh. The Stores and the Comments are in different database tables if that's important
Can someone point me in the right direction?
Thanks!
****EDIT****
The Store.class
public class Store extends CommentEntity {
private String id;
private String chainId;
private String phoneNbr;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getChainId() {
return chainId;
}
public void setChainId(String chainId) {
this.chainId = chainId;
}
public String getPhoneNbr() {
return phoneNbr;
}
public void setPhoneNbr(String phoneNbr) {
this.phoneNbr = phoneNbr;
}
#Override
public String toString() {
return "Store{" + "id=" + id + ", chainId=" + chainId + '}';
}
#Override
public String getCommentIdentifier() {
return id;
}
}
The CommentEntity.Class
public abstract class CommentEntity {
private int commentsCount;
public int getCommentsCount() {
return commentsCount;
}
public void setCommentsCount(int commentsCount) {
this.commentsCount = commentsCount;
}
public abstract String getCommentIdentifier();
}
Thank you for input, I hadn't even reflected over the ImageView / String.
Two issues:
First, you need to distinguish between the data the cells in your column are displaying, and the cells that actually display those data. The cellValueFactory determines the data that are displayed. The PropertyValueFactory is a cellValueFactory implementation that references a JavaFX Property, so when you call
storeNumberColumn.setCellValueFactory(new PropertyValueFactory<Store, String>("id"));
it effectively tells the cells in the storeNumberColumn to call the idProperty() method on the Store object in the current row to get the data for the cell. (If no such method exists, it will try to use getId() as a backup plan.)
By default, you get a cellFactory that displays text resulting from calling toString() on the data generated by the cellValueFactory. In the case where your data are simply Strings, this is usually what you need. In other cases, you often need to provide a cellFactory of your own to get the correct way to display the data.
In your case, the data for the commentColumn are simply the number of comments. You are going to display that by choosing an image based on that numeric value.
So you should have
TableColumn<Store, Number> commentColumn = new TableColumn<>("Comments");
For the cellValueFactory, you can just use
commentColumn.setCellValueFactory(new PropertyValueFactory<>("commentsCount"));
Then you need a cellFactory that displays the appropriate ImageView:
commentColumn.setCellFactory(new Callback<TableColumn<Store, Number>, new TableCell<Store, Number>>() {
#Override
public TableCell<Store, Number>() {
private ImageView imageView = new ImageView();
#Override
public void updateItem(Number numberOfComments, boolean empty) {
super.updateItem(count, empty) ;
if (empty) {
setGraphic(null);
} else {
if (numberOfComments.intValue() == 0) {
setGraphic(null);
} else if (numberOfComments.intValue() == 1) {
imageView.setImage(new Image(COMMENT_SINGLE_FLAG_SOURCE));
setGraphic(imageView);
} else {
imageView.setImage(new Image(COMMENT_DOUBLE_FLAG_SOURCE));
setGraphic(imageView);
}
}
}
}
});
The second issue is actually about the update. A TableView keeps its contents "live" by observing JavaFX properties that are provided by the cellValueFactory as ObservableValues. If the value might change while the table is displayed, you must provide an actual property that can be observed: using a ReadOnlyObjectWrapper is no good (because it's read only, so it's wrapped value will not change). The PropertyValueFactory will also return a ReadOnlyObjectWrapper if you do not have JavaFX property accessor methods (i.e. if it is only using getXXX() methods to access the data). So your model class must provide JavaFX Properties.
You can make an immediate fix to this by updating CommentEntity to use an IntegerProperty:
public abstract class CommentEntity {
private final IntegerProperty commentsCount = new SimpleIntegerProperty();
public final int getCommentsCount() {
return commentsCountProperty().get();
}
public final void setCommentsCount(int commentsCount) {
commentsCountProperty().set(commentsCount);
}
public IntegerProperty commensCountProperty() {
return commentsCount ;
}
public abstract String getCommentIdentifier();
}
I would also strongly recommend updating the Store class to use JavaFX Properties in a similar manner.
I've got a CSV in the format...
Kitten URL,Kitten Name,# of Reviews,Rating,Categories,,,,,,,,,,,,,
www.happykitten.com,happykittem.com,111746,7.8,Clothes & Fashion,Fashion Accessories,Ladies wear,Menswear,,,,,,,,,,
animedkitten.co.uk,Animed Kitten,33918,9.6,Pets,,,,,,,,,,,,,
So the first columns are Kitten URL,Kitten Name,# of Reviews,Rating then the rest are the possible categories listed as extra properties.
I'm trying to use Spring batch so I'm specifying the dumb object to represent this CSV. The first problem I've got is (using the example from Spring documentation I don't see how I can parse a CSV with spaces in the title. Is it possible to use Spring batch like this? Can I annotate each getting like in Hibernate with the title of the csv column?
My dumb object was going to be something like...
public class ImportDataObject {
private String kittenUrl;
private String kittenName;
private int numOfReviews;
public String getKittenUrl() {
return kittenUrl;
}
public void setKittenUrl(String kittenUrl) {
this.kittenUrl = kittenUrl;
}
public String getKittenName() {
return kittenName;
}
public void setKittenName(String kittenName) {
this.kittenName = kittenName;
}
public int getNumOfReviews() {
return numOfReviews;
}
public void setNumOfReviews(int numOfReviews) {
this.numOfReviews = numOfReviews;
}
}
I only really want to read the first 2 columns, append some strings, then persist the rest of the CSV.
I'm also considering the best approach to use for these multiple commas afterwards. Unfortunately this is how I've got the data and it's not something I can change.
You can implement FieldSetMapper for your object and then set it to your DefaultLineMapper. Your implementation of FieldSetMapper can work on positions and you can parse only first few positions and set it to your bean.
Here is suggestion based on code from URL you posted:
reader.setLineMapper(new DefaultLineMapper<ImportDataObject>());
setFieldSetMapper(new ImportDataObjectFieldSetMapper());
}});
setLinesToSkip(1); //skip header since read int will throw exception and I assume you do not need header info
}});
Then changes to POJO object to save list of categories:
public class ImportDataObject {
private String kittenUrl;
private String kittenName;
private int numOfReviews;
private int rating; //add getters and setters
private List<String> categories; //add getters and setters
public String getKittenUrl() {
return kittenUrl;
}
public void setKittenUrl(String kittenUrl) {
this.kittenUrl = kittenUrl;
}
public String getKittenName() {
return kittenName;
}
public void setKittenName(String kittenName) {
this.kittenName = kittenName;
}
public int getNumOfReviews() {
return numOfReviews;
}
public void setNumOfReviews(int numOfReviews) {
this.numOfReviews = numOfReviews;
}
}
And here is FieldSetMapper:
public class ImportDataObjectFieldSetMapper implements FieldSetMapper<ImportDataObject> {
#Override
public ImportDataObject mapFieldSet(final FieldSet fieldSet) throws BindException {
final ImportDataObject importDataObject = new ImportDataObject();
importDataObject.setKittenUrl(fieldSet.readString(0));
importDataObject.setKittenName(fieldSet.readString(1));
importDataObject.setNumOfReviews(fieldSet.readInt(2));
importDataObject.setRating(fieldSet.readInt(3));
importDataObject.setCategories(new ArrayList<String>());
for (int i = 4; i < fieldSet.getFieldCount(); i++) {
importDataObject.getCategories().add(fieldSet.readString(i));
}
return importDataObject;
}
}
i want to split the mProductType is one list and mRetailerid is another list.how can i get it ????
public class RetailerNames implements Serializable{
private String mProductType;
private String mRetailerid;
public String getmProductType() {
return mProductType;
}
public void setmProductType(String mProductType) {
this.mProductType = mProductType;
}
public String getmRetailerid() {
return mRetailerid;
}
public void setmRetailerid(String mRetailerid) {
this.mRetailerid = mRetailerid;
}
#Override
public String toString() {
return mProductType + "," +
mRetailerid ;
}
I have used below code :
ArrayList<RetailerNames> retailerNamesList = (ArrayList<RetailerNames>) getIntent().getExtras().getSerializable("ProductsDetailsDescriptionPage");
System.out.println("The retailer details are"+" "+retailerNamesList);
Now my current output is:
The retailer details are [Krish,48, Danesh,47]
But i want to get the one list like [Krish,Danesh] .and [48,47] is separate another list.How can i do ???
please give me solution ???
please give me a ideas to split the array list to separate list???
ArrayList list = new ArrayList();
Iterator<RetailerNames > retaileriterator = retailerNamesList.iterator();
while(retaileriterator.hasNext()){
id=retaileriterator .next().getmRetailerid();
System.out.println(id);
list.add(id);
}
System.out.println(list);
In my condition getLocationDetails return arraylist
and LocationDetails is POJO same like your class RetailerNames
Iterator<LocationDetails> it= getUserLocationsWrapper.getLocationDetails().iterator();
while(locationCitiDetailsItr.hasNext()){
locationCitiDetailsItr.next().getCity());
}
same i think try this one
Iterator<RetailerNames > retaileriterator = retailerNamesList.iterator();
while(retaileriterator.hasNext()){
Object id=retaileriterator .next().getmRetailerid();
//add this id into another list
//same RetailerNames
}
use nested array
Put [Krish,48] is one list and
[damesh,47] in another list and put both the list in one main array list
Use like this
public class RetailerNames implements Serializable{
private String mProductType;
private String mRetailerid;
public String getmProductType() {
return mProductType;
}
public void setmProductType(String mProductType) {
this.mProductType = mProductType;
}
public String getmRetailerid() {
return mRetailerid;
}
public void setmRetailerid(String mRetailerid) {
this.mRetailerid = mRetailerid;
}
#Override
public String toString() {
return + mProductType + ","
+ mRetailerid +; //Remove "[" this..
}
And,
ArrayList<RetailerNames> retailerNamesList = (ArrayList<RetailerNames>) getIntent().getExtras().getSerializable("ProductsDetailsDescriptionPage");
System.out.println("The retailer details are"+" "+retailerNamesList);
Now try
Object temp[]=retailerNamesList.toArray();
String[] values=temp.toString().split(",");
String names=values[0];
String names=values[1];