দুটি বস্তুর গভীর তুলনা করার জন্য কি জাভা প্রতিচ্ছবি ইউটিলিটি আছে?


99

আমি clone()একটি বড় প্রকল্পের অভ্যন্তরে বিভিন্ন ক্রিয়াকলাপের জন্য ইউনিট পরীক্ষা লেখার চেষ্টা করছি এবং আমি ভাবছি যে কোথাও কোনও বিদ্যমান শ্রেণি রয়েছে যা একই ধরণের দুটি বস্তু নিতে সক্ষম, গভীর তুলনা করে, এবং যদি তারা বলছে যে 'অভিন্ন বা না?


4
এই শ্রেণিটি কীভাবে জানবে যে বস্তুর গ্রাফের একটি নির্দিষ্ট সময়ে এটি অভিন্ন বস্তুগুলি গ্রহণ করতে পারে, বা কেবল একই রেফারেন্সগুলি?
জেড

আদর্শভাবে এটি যথেষ্ট পরিমাণে কনফিগারযোগ্য হবে :) আমি এমন কিছু স্বয়ংক্রিয় সন্ধান করছি যাতে নতুন ক্ষেত্রগুলি যুক্ত করা (এবং ক্লোন নয়) পরীক্ষা তাদের সনাক্ত করতে পারে।
উরি

4
আমি যা বলতে চাইছি তা হ'ল আপনাকে যেভাবেই তুলনাগুলি কনফিগার করতে হবে (অর্থাত্ বাস্তবায়ন করতে হবে)। তাহলে কেন আপনার ক্লাসগুলিতে সমান পদ্ধতিটি ওভাররাইড করে তা ব্যবহার করবেন না?
জেড

4
যদি কোনও বড় জটিল অবজেক্টের জন্য সমান মিথ্যা ফেরত দেয় তবে আপনি কোথায় শুরু করবেন? আপনি বস্তুকে মাল্টি-লাইন স্ট্রিংয়ে রূপান্তর এবং স্ট্রিং তুলনা করা থেকে অনেক ভাল। তারপরে আপনি দেখতে পাবেন যেখানে দুটি বস্তু আলাদা। ইন্টেলিজ একটি "পরিবর্তন" তুলনা উইন্ডোটি পপ আপ করে যা দুটি ফলাফলের মধ্যে একাধিক পরিবর্তনগুলি সন্ধান করতে সহায়তা করে অর্থাৎ এটি assertEquals (স্ট্রিং 1, স্ট্রিং 2) এর আউটপুট বোঝে এবং আপনাকে তুলনা উইন্ডো দেয়।
পিটার লরি

এখানে কিছু সত্যিই ভাল উত্তর রয়েছে, গ্রহণযোগ্য উত্তর ছাড়াও, যেগুলি সমাধিস্থ করা হয়েছে বলে মনে হয়
ব্যবহারকারী 1445967

উত্তর:


63

ইউনিটিলসের এই কার্যকারিতা রয়েছে:

জাভা ডিফল্ট / নাল মান অগ্রাহ্য করা এবং সংগ্রহের ক্রম উপেক্ষা করার মতো বিভিন্ন বিকল্পের সাথে প্রতিবিম্বের মাধ্যমে সমতা দৃ as়তা


10
আমি এই ফাংশনটির জন্য কিছু পরীক্ষা করেছি এবং এটি একটি গভীর তুলনা করে বলে মনে হচ্ছে যেখানে ইক্যুয়ালসুগল্ডার হিসাবে না।
হাওয়ার্ড মে

এটি ক্ষণস্থায়ী ক্ষেত্রগুলি উপেক্ষা না করার উপায় আছে?
পিঞ্চ

@ পিঞ্চ আমি আপনাকে শুনছি। আমি বলব গভীর তুলনা সরঞ্জামটি unitilsসঠিকভাবে ত্রুটিযুক্ত কারণ এটি ভেরিয়েবলগুলির সাথে তুলনা করে এমনকি যদি তাদের পর্যবেক্ষণযোগ্য প্রভাব নাও আসে । ভেরিয়েবলের তুলনা করার আরেকটি (অনাকাঙ্ক্ষিত) পরিণতি হ'ল খাঁটি বন্ধ (তাদের নিজস্ব কোনও রাজ্য নেই) সমর্থিত নয়। এছাড়াও, তুলনা করা অবজেক্টগুলি একই রানটাইম টাইপের হওয়া দরকার। আমি আমার আস্তিনগুলি ঘূর্ণিত করেছি এবং এই উদ্বেগগুলির সমাধান করার জন্য গভীর তুলনা সরঞ্জামটির নিজস্ব সংস্করণ তৈরি করেছি ।
বেলুচিন

@ ওল্ফগ্যাং আমাদেরকে নির্দেশ দেওয়ার জন্য কোনও নমুনা কোড আছে? কোথা থেকে আপনি এই উদ্ধৃতিটি টানলেন?
anon58192932

30

আমি এই প্রশ্ন ভালোবাসি! মূলত কারণ এটি কখনও উত্তর দেওয়া হয় না বা খারাপ উত্তর দেওয়া হয় না। এটি এখনও কেউ খুঁজে পায়নি এর মতো। কুমারী অঞ্চল :)

প্রথম বন্ধ, এমনকি ব্যবহার সম্পর্কে চিন্তা করবেন না equals। চুক্তি equals, যেমন javadoc সংজ্ঞায়িত, একটি সমানতা সম্পর্ক (আত্মবাচক, প্রতিসম এবং সকর্মক) হয় না একটি সমতা সম্পর্ক। তার জন্য এটি এন্টিসিমমেট্রিকও হতে হবে। এর একমাত্র বাস্তবায়ন equals(বা কখনও হতে পারে) একটি সত্য সাম্যতা সম্পর্ক হল java.lang.Object। এমনকি আপনি যদি equalsগ্রাফের সাথে সমস্ত কিছু তুলনা করতে ব্যবহার করেন তবে চুক্তি ভঙ্গ হওয়ার ঝুঁকিটি বেশ বেশি। কার্যকর জোয়ায় জোশ ব্লচ যেমন উল্লেখ করেছেন, সমানদের চুক্তিটি খুব সহজেই ভাঙ্গা যায়:

"সাময়িক চুক্তি সংরক্ষণের সময় কোনও তাত্ক্ষণিক ক্লাস বাড়ানো এবং একটি দিক যুক্ত করার সহজ উপায় নেই"

বুলিয়ান পদ্ধতি আসলে কীভাবে আপনাকে কী করতে পারে তা ছাড়াও? আসল এবং ক্লোনটির মধ্যে সমস্ত পার্থক্যকে প্রকৃতপক্ষে আবদ্ধ করা ভাল লাগবে, আপনি কি ভাবেন না? এছাড়াও, আমি এখানে ধরে নেব যে আপনি গ্রাফের প্রতিটি বস্তুর জন্য তুলনা কোডটি লেখার / বজায় রাখার বিষয়ে বিরক্ত হতে চান না, বরং আপনি এমন কিছু সন্ধান করছেন যা সময়ের সাথে সাথে পরিবর্তনের সাথে সাথে উত্সটি স্কেল করবে।

Soooo, আপনি যা চান তা হ'ল এক ধরণের রাষ্ট্র তুলনা সরঞ্জাম। কীভাবে সেই সরঞ্জামটি প্রয়োগ করা হয় তা সত্যিই আপনার ডোমেন মডেলটির প্রকৃতির এবং আপনার কার্যকারিতা সীমাবদ্ধতার উপর নির্ভরশীল। আমার অভিজ্ঞতায় কোনও জেনেরিক ম্যাজিক বুলেট নেই। এবং এটি প্রচুর পরিমাণে পুনরাবৃত্তির তুলনায় ধীর হবে । তবে ক্লোন ক্রিয়াকলাপের সম্পূর্ণতা পরীক্ষা করার জন্য, এটি কাজটি বেশ ভালভাবে সম্পাদন করবে। আপনার দুটি সেরা বিকল্প হ'ল সিরিয়ালাইজেশন এবং প্রতিবিম্ব।

কিছু সমস্যার মুখোমুখি হবেন:

  • সংগ্রহের ক্রম: দুটি সংকলন একই জিনিসকে ধারণ করলে কি আলাদা হওয়া উচিত তবে আলাদা অর্ডারে?
  • কোন ক্ষেত্রটি উপেক্ষা করবেন: ক্ষণস্থায়ী? স্থির?
  • সমতা টাইপ করুন: ক্ষেত্রের মানগুলি একই ধরণের হওয়া উচিত? বা অন্যটির প্রসারিত করা কি ঠিক হবে?
  • আরও কিছু আছে, তবে আমি ভুলে গেছি ...

এক্সস্ট্রিমটি খুব দ্রুত এবং এক্সএমএলউনিতের সাথে মিলিত কোডের কয়েকটি লাইনে কাজ করবে। এক্সএমএলউনিতটি দুর্দান্ত কারণ এটি সমস্ত পার্থক্যের প্রতিবেদন করতে পারে বা এটির প্রথমটি খুঁজে পাওয়া বন্ধ করে দেয়। এবং এর আউটপুটটিতে আলাদা আলাদা নোডের এক্সপাথ অন্তর্ভুক্ত রয়েছে যা দুর্দান্ত is ডিফল্টরূপে এটি অর্ডারড সংগ্রহগুলি মঞ্জুরি দেয় না, তবে এটি করার জন্য এটি কনফিগার করা যেতে পারে। একটি বিশেষ পার্থক্য হ্যান্ডলার ইনজেকশন (বলা হয় একটিDifferenceListener যাকে ) উপেক্ষা সহ আপনি যেভাবে পার্থক্যগুলি মোকাবেলা করতে চান তা সুনির্দিষ্ট করতে দেয়। তবে, আপনি যত তাড়াতাড়ি সাধারণ কাস্টমাইজেশনের বাইরে কিছু করতে চান, লিখতে অসুবিধা হয় এবং বিশদটি নির্দিষ্ট ডোমেন অবজেক্টের সাথে আবদ্ধ থাকে।

আমার ব্যক্তিগত অগ্রাধিকার হ'ল সমস্ত ঘোষিত ক্ষেত্রগুলিতে চক্রের প্রতিবিম্ব ব্যবহার করা এবং প্রত্যেকটিতে illুকিয়ে দেওয়া, আমার যেতে পার্থক্যের সন্ধান করা। সতর্কতার শব্দ: আপনি যদি স্ট্যাক ওভারফ্লো ব্যতিক্রম পছন্দ না করেন তবে পুনরাবৃত্তি ব্যবহার করবেন না। স্ট্যাকের সাহায্যে জিনিসগুলিকে সুযোগে রাখুন (একটি ব্যবহার করুন aLinkedListঅথবা অন্যকিছু). আমি সাধারণত ক্ষণস্থায়ী এবং স্থিতিশীল ক্ষেত্রগুলিকে অগ্রাহ্য করি এবং আমি ইতিমধ্যে তুলনা করা অবজেক্টের জোড়গুলি এড়িয়ে চলেছি, তাই যদি কেউ স্ব-রেফারেন্সিয়াল কোড লেখার সিদ্ধান্ত নেন তবে আমি অসীম লুপগুলিতে শেষ করি না (তবে আমি সর্বদা আদিম মোড়কের তুলনা করি না কেন যাই হোক না কেন , যেহেতু একই অবজেক্ট রেফগুলি প্রায়শই পুনরায় ব্যবহৃত হয়)। সংগ্রহের ক্রমটিকে অগ্রাহ্য করতে এবং বিশেষ ধরণের বা ক্ষেত্রগুলি উপেক্ষা করতে আপনি সামনের জিনিসগুলি কনফিগার করতে পারেন, তবে আমি টীকাগুলির মাধ্যমে ক্ষেত্রগুলিতে আমার রাজ্যের তুলনা নীতিগুলি সংজ্ঞায়িত করতে চাই। এটি, আইএমএইচও, রানটাইমে ক্লাস সম্পর্কে মেটা ডেটা তৈরি করার জন্য, টীকাগুলির ঠিক কী বোঝানো হয়েছিল। কিছুটা এইরকম:


@StatePolicy(unordered=true, ignore=false, exactTypesOnly=true)
private List<StringyThing> _mylist;

আমি মনে করি এটি আসলেই একটি কঠিন সমস্যা, তবে সম্পূর্ণ সমাধানযোগ্য! এবং একবার আপনার জন্য কাজ করে এমন কিছু হয়ে গেলে, এটি সত্যই, সত্যই, কার্যকর ...

সুতরাং ভালো থাকুন. এবং আপনি যদি এমন কিছু নিয়ে আসেন যা কেবল খাঁটি প্রতিভা, ভাগ করতে ভুলবেন না!


15

জাভা-ব্যবহারের মধ্যে ডিপক্যুয়ালস এবং ডিপহ্যাশকোড () দেখুন: https://github.com/jdereg/java-util

এই শ্রেণিটি মূল লেখকের অনুরোধ অনুযায়ী ঠিক তাই করে।


4
সতর্কতা: ডিপএকুয়ালস যদি কোনও বস্তুর উপস্থিত থাকে তবে .equals () পদ্ধতি ব্যবহার করে। এটি আপনি যা চান তা নাও হতে পারে।
অ্যাডাম 20

4
এটি কেবলমাত্র ক্লাসে .equals () ব্যবহার করে যদি একটি সমান () পদ্ধতি সুস্পষ্টভাবে যুক্ত করা হয়, অন্যথায় এটি সদস্য দ্বারা সদস্য তুলনা করে। এখানে যুক্তিটি হ'ল কেউ যদি কাস্টম সমান () পদ্ধতি লেখার প্রয়াসে যায় তবে এটি ব্যবহার করা উচিত। ভবিষ্যতের বর্ধন: পতাকা বিদ্যমান থাকলেও এটি সমান () পদ্ধতিগুলিকে উপেক্ষা করার অনুমতি দিন। জাভা-ব্যবহারে দরকারী ইউটিলিটিগুলি রয়েছে যেমন কেসআইসেনসেটিভম্যাপ / সেট।
জন DeRegnaucourt

আমি ক্ষেত্রের তুলনা সম্পর্কে উদ্বিগ্ন। ক্ষেত্রগুলির পার্থক্যটি বস্তুর ক্লায়েন্টের দৃষ্টিকোণ থেকে লক্ষ্য করা যায় না এবং ক্ষেত্রগুলির উপর ভিত্তি করে একটি গভীর তুলনা এটি পতাকাঙ্কিত করে। তদতিরিক্ত, ক্ষেত্রের তুলনা করার জন্য অবজেক্টগুলি একই রানটাইম টাইপের হওয়া দরকার যা সীমাবদ্ধ হতে পারে।
বেলুচিন

উপরে @ বেলুচিনের উত্তর দেওয়ার জন্য, ডিপেকুয়ালস.ডিপইকুয়ালস () সর্বদা ফিল্ড-বাই-ফিল্ড তুলনা করে না। প্রথমত, এটির কোনও পদ্ধতিতে .equals () ব্যবহার করার বিকল্প রয়েছে যদি এটি উপস্থিত থাকে (তবে এটি অবজেক্টে নেই), বা এড়ানো যায়। দ্বিতীয়ত, মানচিত্র / সংগ্রহগুলির তুলনা করার সময় এটি সংগ্রহ বা মানচিত্রের ধরণটি বা সংগ্রহ / মানচিত্রের ক্ষেত্রগুলির দিকে নজর দেয় না। পরিবর্তে, এটি তাদের সাথে যুক্তিযুক্ত তুলনা করে। একটি লিঙ্কডহ্যাশম্যাপ একটি ট্রিম্যাপকে সমান করতে পারে যদি তাদের একই ক্রমে একই সামগ্রী এবং উপাদান থাকে। অ-অর্ডারযুক্ত সংগ্রহ এবং মানচিত্রের জন্য, কেবল আকার এবং গভীর সমতুল্য আইটেমগুলির প্রয়োজন।
জন DeRegnaucourt

মানচিত্র / সংগ্রহগুলির সাথে তুলনা করার সময় এটি সংগ্রহ বা মানচিত্রের ধরণটি বা সংগ্রহ / মানচিত্রের ক্ষেত্রগুলিতে নজর দেয় না। পরিবর্তে, এটি যৌক্তিকভাবে @ জনডে রেগনাকোর্টের সাথে তাদের তুলনা করে , আমি এই যৌক্তিক তুলনাটি যুক্তি করব, publicযা কেবল সংগ্রহ / মানচিত্রের ক্ষেত্রে প্রযোজ্য তার বিপরীতে সমস্ত প্রকারের ক্ষেত্রে কী প্রযোজ্য তা কেবল তুলনা করে ।
বেলুচিন

10

সমান () পদ্ধতিটি ওভাররাইড করুন

এখানে বর্ণিত হিসাবে আপনি ইক্যুয়াল বিল্ডার.রেফলেশনএকুয়ালস () ব্যবহার করে ক্লাসের সমান () সমান পদ্ধতিটি কেবল ওভাররাইড করতে পারেন :

 public boolean equals(Object obj) {
   return EqualsBuilder.reflectionEquals(this, obj);
 }

8

ইন AssertJ , আপনি করতে পারেন:

Assertions.assertThat(expectedObject).isEqualToComparingFieldByFieldRecursively(actualObject);

সম্ভবত এটি সমস্ত ক্ষেত্রে কাজ করবে না, তবে এটি আপনার মনে হতে পারে এমন আরও বেশি ক্ষেত্রে কাজ করবে।

এখানে ডকুমেন্টেশন কী বলে:

জোর দিয়ে নিন যে পরীক্ষার অধীনে থাকা অবজেক্টটি সম্পত্তি / ক্ষেত্রের তুলনায় (উত্তরাধিকারসূত্রে অন্তর্ভুক্ত) দ্বারা সম্পত্তি / ক্ষেত্র পুনরাবৃত্ত করার উপর ভিত্তি করে প্রদত্ত বস্তুর সমান। বাস্তবের সমান বাস্তবায়ন যদি আপনার উপযুক্ত না হয় তবে এটি কার্যকর হতে পারে। পুনরাবৃত্ত সম্পত্তি / ক্ষেত্রের তুলনা প্রয়োগ করা হয় না কাস্টম সমান বাস্তবায়নের ক্ষেত্রগুলিতে, অর্থাত্ ওভাররাইড সমান পদ্ধতিটি ক্ষেত্রের তুলনায় ক্ষেত্রের পরিবর্তে ব্যবহৃত হবে।

পুনরাবৃত্তির তুলনা চক্র পরিচালনা করে। ডিফল্টরূপে ভাসমানগুলির সাথে তুলনা করা হয় 1.0E-6 এর নির্ভুলতার সাথে এবং 1.0E-15 এর সাথে ডাবলস।

আপনি প্রতি (নেস্টেড) ক্ষেত্রগুলিতে একটি কাস্টম তুলক নির্দিষ্ট করতে পারেন বা যথাক্রমে কমপোরেটরফরফিল্ডস (তুলনাকারী, স্ট্রিং ...) এবং কমার্পেটর ফোরটাইপ (তুলনকারী, শ্রেণি) ব্যবহার করে টাইপ করতে পারেন।

তুলনা করার জন্য অবজেক্টগুলি বিভিন্ন ধরণের হতে পারে তবে একই বৈশিষ্ট্য / ক্ষেত্র থাকতে হবে। উদাহরণস্বরূপ যদি প্রকৃত অবজেক্টটির একটি নাম স্ট্রিং ফিল্ড থাকে তবে এটি অন্য বস্তুরও একটি থাকার প্রত্যাশা করে। যদি কোনও জিনিসের ক্ষেত্র এবং একই নামের একটি সম্পত্তি থাকে তবে সম্পত্তি মানটি ক্ষেত্রের উপরে ব্যবহার করা হবে।


4
isEqualToComparingFieldByFieldRecursivelyএখন অবচয় করা হয়েছে। assertThat(expectedObject).usingRecursiveComparison().isEqualTo(actualObject);পরিবর্তে ব্যবহার করুন :)
dargmuesli

7

কেবলমাত্র হাইবারনেট এনভার্স দ্বারা সংশোধিত দুটি সত্তার উদাহরণগুলির তুলনা বাস্তবায়ন করতে হয়েছিল। আমি আমার নিজস্ব লিখতে শুরু করেছি তবে নীচের কাঠামোটি পেয়েছি।

https://github.com/SQiShER/java-object-diff

আপনি একই ধরণের দুটি বস্তুর তুলনা করতে পারেন এবং এটি পরিবর্তন, সংযোজন এবং অপসারণগুলি প্রদর্শন করবে। যদি কোনও পরিবর্তন না হয় তবে বস্তুগুলি সমান (তত্ত্ব অনুসারে)। গ্রাহকদের জন্য টীকাগুলি সরবরাহ করা হয় যা চেক চলাকালীন উপেক্ষা করা উচিত। সাম্যতা যাচাইয়ের চেয়ে ফ্রেমের কাজের অনেক বেশি বিস্তৃত অ্যাপ্লিকেশন রয়েছে, অর্থাত্ আমি একটি পরিবর্তন-লগ তৈরি করতে ব্যবহার করছি।

এর পারফরম্যান্স ঠিক আছে, জেপিএ সত্তাগুলির সাথে তুলনা করার সময়, প্রথমে সত্তা ব্যবস্থাপকের কাছ থেকে এটিকে আলাদা করে রাখার বিষয়ে নিশ্চিত হন।


6

আমি ইউএসএন স্ট্রিম:

/**
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object o) {
    XStream xstream = new XStream();
    String oxml = xstream.toXML(o);
    String myxml = xstream.toXML(this);

    return myxml.equals(oxml);
}

/**
 * @see java.lang.Object#hashCode()
 */
@Override
public int hashCode() {
    XStream xstream = new XStream();
    String myxml = xstream.toXML(this);
    return myxml.hashCode();
}

4
তালিকাগুলি ব্যতীত অন্য সংগ্রহগুলি উপাদানগুলিকে বিভিন্ন ক্রমে ফিরিয়ে দিতে পারে, সুতরাং স্ট্রিং তুলনা ব্যর্থ হবে।
অ্যালেক্সি বেরেজকিন

এছাড়াও ধারাবাহিক নয় এমন ক্লাসগুলি ব্যর্থ হবে
জুয়েলচ

5

http://www.unitils.org/tutorial-reflectionassert.html

public class User {

    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }
}
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);

4
বিশেষত দরকারী যদি আপনার উত্পন্ন ক্লাসগুলি পরিচালনা করতে হয়, যেখানে সমান সম্পর্কে আপনার কোনও প্রভাব নেই!
ম্যাথিয়াস বি

4
stackoverflow.com/a/1449051/829755 ইতিমধ্যে এটি উল্লেখ করেছে। আপনার পোস্টটি সম্পাদনা করা উচিত ছিল
ব্যবহারকারীর 829755

4
@ user829755 এইভাবে আমি পয়েন্ট হারিয়েছি। পয়েন্ট গেম সম্পর্কে তাই)) লোকেরা কাজের জন্য ক্রেডিট পেতে পছন্দ করে, আমিও আছি।
গ্যাভেনকোয়া

3

Hamcrest ম্যাচার হয়েছে samePropertyValuesAs । তবে এটি জাভাবিয়ান কনভেনশন (গেটার এবং সেটটার ব্যবহার করে) এর উপর নির্ভর করে। যে বস্তুগুলির সাথে তুলনা করতে হবে তাদের বৈশিষ্ট্যের জন্য গিটার এবং সেটার না থাকলে এটি কার্যকর হবে না।

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserTest {

    @Test
    public void asfd() {
        User user1 = new User(1, "John", "Doe");
        User user2 = new User(1, "John", "Doe");
        assertThat(user1, samePropertyValuesAs(user2)); // all good

        user2 = new User(1, "John", "Do");
        assertThat(user1, samePropertyValuesAs(user2)); // will fail
    }
}

ব্যবহারকারীর শিম - গিটার এবং সেটটার সহ

public class User {

    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirst() {
        return first;
    }

    public void setFirst(String first) {
        this.first = first;
    }

    public String getLast() {
        return last;
    }

    public void setLast(String last) {
        this.last = last;
    }

}

আপনার কোনও POJO না হওয়া পর্যন্ত এটি দুর্দান্ত কাজ করে যা isFooকোনও Booleanসম্পত্তির জন্য পঠন পদ্ধতি ব্যবহার করে না । এটি ঠিক করার জন্য একটি পিআর রয়েছে যা ২০১ 2016 সাল থেকে উন্মুক্ত। github.com/hamcrest/ JavaHamcrest
pull/

2

যদি আপনার অবজেক্টগুলি সিরিয়ালাইজেবল কার্যকর করে তবে আপনি এটি ব্যবহার করতে পারেন:

public static boolean deepCompare(Object o1, Object o2) {
    try {
        ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
        ObjectOutputStream oos1 = new ObjectOutputStream(baos1);
        oos1.writeObject(o1);
        oos1.close();

        ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
        ObjectOutputStream oos2 = new ObjectOutputStream(baos2);
        oos2.writeObject(o2);
        oos2.close();

        return Arrays.equals(baos1.toByteArray(), baos2.toByteArray());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

1

আপনার লিঙ্কযুক্ত তালিকার উদাহরণটি পরিচালনা করা এতটা কঠিন নয়। কোডটি দুটি অবজেক্টের গ্রাফকে অতিক্রম করার সাথে সাথে এটি পরিদর্শন করা বস্তুগুলিকে একটি সেট বা মানচিত্রে রাখে। অন্য কোনও বস্তুর রেফারেন্সে প্রবেশের আগে, এই সেটটি ইতিমধ্যে বস্তুটি ট্র্যাভারসড হয়েছে কিনা তা পরীক্ষা করা হয়। যদি তা হয় তবে আর এগিয়ে যাওয়ার দরকার নেই।

আমি উপরের ব্যক্তির সাথে সম্মত যিনি বলেছিলেন যে লিংকডলিস্টটি ব্যবহার করুন (স্ট্যাকের মতো তবে এটিতে সিঙ্ক্রোনাইজড পদ্ধতি ছাড়াই এটি দ্রুত)। স্ট্যাক ব্যবহার করে অবজেক্টের গ্রাফের সন্ধান করা, প্রতিটি ক্ষেত্রের প্রতিবিম্বটি ব্যবহার করার সময়, এটি আদর্শ সমাধান। একবার লিখিত, এই "বাহ্যিক" সমান () এবং "বাহ্যিক" হ্যাশকোড () সমস্ত সমান () এবং হ্যাশকোড () পদ্ধতিগুলির কল করা উচিত। আর কখনও আপনার গ্রাহকের সমান () পদ্ধতির দরকার নেই।

আমি কিছুটা কোড লিখেছি যা গুগল কোডে তালিকাভুক্ত একটি সম্পূর্ণ অবজেক্ট গ্রাফকে অনুসরণ করে। Json-io (http://code.google.com/p/json-io/) দেখুন। এটি JSON- এ একটি জাভা অবজেক্ট গ্রাফকে সিরিয়ালাইজ করে এবং এ থেকে ডিজিট্রাইজড। এটি পাবলিক কনস্ট্রাক্টর, সিরিয়ালাইজেবল বা না সিরিয়ালাইজেবল, ইত্যাদি ছাড়া সমস্ত জাভা অবজেক্ট পরিচালনা করে same বিটিডব্লিউ, জসনরিডার / জসন রাইটার (জসন-আইও) সাধারণত অন্তর্নির্মিত অবজেক্টআইপুটস্ট্রিম / অবজেক্টআউটপুট স্ট্রিমের চেয়ে দ্রুত হয়।

এই JsonReader / JsonWriter তুলনা জন্য ব্যবহার করা যেতে পারে, তবে এটি হ্যাশকোড সাহায্য করবে না। আপনি যদি সর্বজনীন হ্যাশকোড () এবং সমান () চান তবে এটির নিজস্ব কোড দরকার। আমি জেনেরিক গ্রাফ দর্শকের সাথে এটি টানতে সক্ষম হতে পারি। আমরা দেখব.

অন্যান্য বিবেচনা - স্থিতিশীল ক্ষেত্র - এটি সহজ - এগুলি এড়ানো যায় কারণ সমস্ত সমান () উদাহরণগুলির স্থির ক্ষেত্রগুলির জন্য সমান মূল্য থাকবে, কারণ স্থির ক্ষেত্রগুলি সমস্ত দৃষ্টান্ত জুড়ে ভাগ করা হয়।

ক্ষণস্থায়ী ক্ষেত্র হিসাবে - এটি একটি নির্বাচনযোগ্য বিকল্প হবে। কখনও কখনও আপনি স্থানান্তরকারী অন্য সময় না গণনা করতে পারেন। "কখনও কখনও আপনি বাদামের মতো অনুভব করেন, কখনও কখনও করেন না" "

Json-io প্রকল্পে ফিরে দেখুন (আমার অন্যান্য প্রকল্পের জন্য) এবং আপনি বহিরাগত সমান () / হ্যাশকোড () প্রকল্প পাবেন। এটির জন্য এখনও আমার নাম নেই, তবে তা সুস্পষ্ট হবে।


0

আমার ধারণা আপনি এটি জানেন তবে তত্ত্ব অনুসারে আপনার সর্বদা ওভাররাইড করা উচিত e দুটি বস্তু সত্যই সমান বলে দাবি করার জন্য সমান। এটি বোঝায় যে তারা তাদের সদস্যদের উপরে ওভাররাইড করা .সম্পূর্ণ পদ্ধতিগুলি পরীক্ষা করে।

এই জাতীয় জিনিসটি কেন .সাম্যগুলিকে অবজেক্টে সংজ্ঞায়িত করা হয়।

এটি যদি ধারাবাহিকভাবে করা হয়ে থাকে তবে আপনার কোনও সমস্যা হবে না।


4
সমস্যাটি হ'ল আমি এটি লিখছি না এমন একটি বৃহত বিদ্যমান কোডবেসের জন্য এটি পরীক্ষা করে স্বয়ংক্রিয় করতে চাই ... :)
উরি

0

এত গভীর তুলনার জন্য একটি থামার গ্যারান্টি একটি সমস্যা হতে পারে। নিম্নলিখিতগুলি কি করা উচিত? (আপনি যদি এই ধরণের তুলনামূলক প্রয়োগ করেন তবে এটি ভাল ইউনিট পরীক্ষা করবে))

LinkedListNode a = new LinkedListNode();
a.next = a;
LinkedListNode b = new LinkedListNode();
b.next = b;

System.out.println(DeepCompare(a, b));

এখানে আরও একটি:

LinkedListNode c = new LinkedListNode();
LinkedListNode d = new LinkedListNode();
c.next = d;
d.next = c;

System.out.println(DeepCompare(c, d));

আপনার যদি নতুন প্রশ্ন থাকে তবে দয়া করে প্রশ্ন জিজ্ঞাসা বোতামটি ক্লিক করে এটি জিজ্ঞাসা করুন । যদি এই প্রসঙ্গে সরবরাহ করতে সহায়তা করে তবে এই প্রশ্নের একটি লিঙ্ক অন্তর্ভুক্ত করুন।
ইয়ংহব্বিট

@ ইয়ংহব্বিট: না এটি কোনও নতুন প্রশ্ন নয়। উত্তরের একটি প্রশ্ন চিহ্ন সেই পতাকাটিকে উপযুক্ত করে না। আরও মনোযোগ দিন।
বেন ভয়েগট

এ থেকে: এটি Using an answer instead of a comment to get a longer limit and better formatting.যদি মন্তব্য হয় তবে উত্তর বিভাগটি কেন ব্যবহার করবেন? এজন্য আমি এটি পতাকাঙ্কিত করেছি। না কারণ ?। এই উত্তরটি ইতিমধ্যে অন্য কেউ ফ্ল্যাগ করেছেন, যিনি মন্তব্যটি পিছনে রাখেন নি। আমি স্রেফ এটি পর্যালোচনা সারিতে পেয়েছি। আমার খারাপ হতে পারে যে, আমি আরও যত্নবান হওয়া উচিত ছিল।
ইয়ংহব্বিট

0

আমি মনে করি রায় হুলা সমাধান দ্বারা অনুপ্রাণিত করা সবচেয়ে সহজ সমাধান হ'ল বস্তুটিকে সিরিয়ালাইজ করা এবং তারপরে কাঁচা ফলাফলকে গভীরভাবে তুলনা করা।

সিরিয়ালাইজেশন বাইট, জসন, এক্সএমএল বা সাধারণ টো স্ট্রিং ইত্যাদি হতে পারে। টুস্ট্রিং সস্তা বলে মনে হচ্ছে। লম্বোক আমাদের জন্য বিনামূল্যে সহজেই কাস্টমাইজেবল টোস্ট্রিং তৈরি করে। নীচে উদাহরণ দেখুন।

@ToString @Getter @Setter
class foo{
    boolean foo1;
    String  foo2;        
    public boolean deepCompare(Object other) { //for cohesiveness
        return other != null && this.toString().equals(other.toString());
    }
}   

0

অ্যাপাচি আপনাকে কিছু দেয়, উভয় বস্তুকে স্ট্রিংয়ে রূপান্তর করে স্ট্রিংগুলির তুলনা করে, তবে আপনাকে টু স্ট্রিংকে ওভাররাইড করতে হবে ()

obj1.toString().equals(obj2.toString())

টু স্ট্রিংকে ওভাররাইড করুন ()

যদি সমস্ত ক্ষেত্র আদিম ধরণের হয়:

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
@Override
public String toString() {return 
ReflectionToStringBuilder.toString(this);}

আপনার যদি আদিম ক্ষেত্র এবং / অথবা সংগ্রহ এবং / বা মানচিত্র না থাকে:

// Within class
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
@Override
public String toString() {return 
ReflectionToStringBuilder.toString(this,new 
MultipleRecursiveToStringStyle());}

// New class extended from Apache ToStringStyle
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.*;

public class MultipleRecursiveToStringStyle extends ToStringStyle {
private static final int    INFINITE_DEPTH  = -1;

private int                 maxDepth;

private int                 depth;

public MultipleRecursiveToStringStyle() {
    this(INFINITE_DEPTH);
}

public MultipleRecursiveToStringStyle(int maxDepth) {
    setUseShortClassName(true);
    setUseIdentityHashCode(false);

    this.maxDepth = maxDepth;
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
    if (value.getClass().getName().startsWith("java.lang.")
            || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
        buffer.append(value);
    } else {
        depth++;
        buffer.append(ReflectionToStringBuilder.toString(value, this));
        depth--;
    }
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, 
Collection<?> coll) {
    for(Object value: coll){
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
    }
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, Map<?, ?> map) {
    for(Map.Entry<?,?> kvEntry: map.entrySet()){
        Object value = kvEntry.getKey();
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
        value = kvEntry.getValue();
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
    }
}}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.